From c21bad6e39bed7706420f5391b5561d2a5931093 Mon Sep 17 00:00:00 2001 From: Adrian Webb Date: Sat, 17 Oct 2026 02:47:29 -0400 Subject: [PATCH 01/24] test: expose absent canonical preactivation Reporter selection and duplicate joint closeout projection --- .../graph/workday-execution-projector.test.ts | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/tests/unit/control-plane/capacity/execution/graph/workday-execution-projector.test.ts b/tests/unit/control-plane/capacity/execution/graph/workday-execution-projector.test.ts index 5c8fb3cd8..5615e6ce6 100644 --- a/tests/unit/control-plane/capacity/execution/graph/workday-execution-projector.test.ts +++ b/tests/unit/control-plane/capacity/execution/graph/workday-execution-projector.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'vitest'; -import { DEFAULT_WORKDAY_POLICY, compileWorkday, validateExecutionGraph, type AgentDefinition } from '@treeseed/sdk/agent-capacity'; +import { DEFAULT_WORKDAY_POLICY, compileWorkday, appliedWorkdaySchema, validateExecutionGraph, type AgentDefinition } from '@treeseed/sdk/agent-capacity'; import { projectActiveWorkdays } from '../../../../../../src/api/capacity/policy/execution/workday-execution-projector.ts'; import { workdayParticipants } from '../../../../../../src/api/capacity/policy/execution/workday-participants.ts'; @@ -330,3 +330,21 @@ describe('workday living-graph projection', () => { expect(graph.nodes.filter((node) => node.kind === 'planning')).toHaveLength(0); }); }); + +function explicitReportingSelection(){ + const selected={...definition('reporter'),id:'sdk/digest-writer',agentClass:'digest-writer'},other={...definition('reporter'),id:'api/digest-writer',agentClass:'digest-writer'}; + const snapshot={sdk:{agents:[{definition:selected,activities:['planning']}]},api:{agents:[{definition:other,activities:['planning']}]}},participants=workdayParticipants({agentProfilesByProjectId:snapshot}); + // Proposed necessary canonical contract input; current compileWorkday drops it. + const input={id:'one-configured-closeout',teamId:'team',policyId:'default',policyRevision:1,executionMode:'simulation' as const,startsAt:'2026-10-17T00:00:00.000Z',agentIds:participants.map(value=>value.id),reportingAgentId:selected.id,policy:{...DEFAULT_WORKDAY_POLICY,durationSeconds:3600,maximumConcurrency:5,communicationConcurrency:5}}; + return{selected,other,snapshot,input,plan:compileWorkday(input)}; +} + +it('retains one explicitly selected configured Reporter in the canonical applied Workday before activation without a second authority',()=>{ + const f=explicitReportingSelection(),held=structuredClone(f.input);expect.soft(f.plan).toMatchObject({state:'planned',reportingAgentId:f.selected.id});expect.soft(appliedWorkdaySchema.safeParse({...f.plan,reportingAgentId:f.selected.id}).success).toBe(true);expect(f.input).toEqual(held); +}); + +it('projects only the selected configured closeout Reporter while preserving every participating project planning contributor',()=>{ + const f=explicitReportingSelection(),source={id:f.plan.id,teamId:'team',parameters:{appliedPlan:f.plan,scheduledProjectIds:['sdk','api'],agentProfilesByProjectId:f.snapshot}},held=structuredClone(source); + const projected=projectActiveWorkdays({teamId:'team',revision:1,profiles:{'sdk:digest-writer':f.selected,'api:digest-writer':f.other},sources:[source]}); + expect.soft(projected.nodes.filter(node=>node.kind==='planning').map(node=>node.projectId).sort()).toEqual(['api','sdk']);expect.soft(projected.nodes.filter(node=>node.kind==='reporting')).toHaveLength(1);expect.soft(projected.nodes.filter(node=>node.kind==='reporting').map(node=>node.projectId)).toEqual(['sdk']);expect(source).toEqual(held); +}); From c9ca117b0cd30a0b0f484c875639f499f5846cb7 Mon Sep 17 00:00:00 2001 From: Adrian Webb Date: Sat, 17 Oct 2026 02:58:04 -0400 Subject: [PATCH 02/24] test: deny ambiguous or moved configured reporting authority before projection --- .../graph/workday-execution-projector.test.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/unit/control-plane/capacity/execution/graph/workday-execution-projector.test.ts b/tests/unit/control-plane/capacity/execution/graph/workday-execution-projector.test.ts index 5615e6ce6..c9695c592 100644 --- a/tests/unit/control-plane/capacity/execution/graph/workday-execution-projector.test.ts +++ b/tests/unit/control-plane/capacity/execution/graph/workday-execution-projector.test.ts @@ -348,3 +348,19 @@ it('projects only the selected configured closeout Reporter while preserving eve const projected=projectActiveWorkdays({teamId:'team',revision:1,profiles:{'sdk:digest-writer':f.selected,'api:digest-writer':f.other},sources:[source]}); expect.soft(projected.nodes.filter(node=>node.kind==='planning').map(node=>node.projectId).sort()).toEqual(['api','sdk']);expect.soft(projected.nodes.filter(node=>node.kind==='reporting')).toHaveLength(1);expect.soft(projected.nodes.filter(node=>node.kind==='reporting').map(node=>node.projectId)).toEqual(['sdk']);expect(source).toEqual(held); }); + +it('denies omitted ambiguous foreign duplicate and moved reporting authority without replacing the captured selection',()=>{ + const f=explicitReportingSelection(),profiles={'sdk:digest-writer':f.selected,'api:digest-writer':f.other},parameters={appliedPlan:f.plan,scheduledProjectIds:['sdk','api'],agentProfilesByProjectId:f.snapshot}; + for(const reportingAgentId of [undefined,'foreign/digest-writer','sdk/missing']) { + const plan={...f.plan};delete plan.reportingAgentId;Object.assign(plan,reportingAgentId===undefined?{}:{reportingAgentId}); + const source={id:plan.id,teamId:'team',parameters:{...parameters,appliedPlan:plan}},held=structuredClone(source); + expect(()=>projectActiveWorkdays({teamId:'team',revision:1,profiles,sources:[source]})).toThrow();expect(source).toEqual(held); + } + const duplicate={...f.other,id:f.selected.id}; + expect(()=>projectActiveWorkdays({teamId:'team',revision:1,profiles:{...profiles,'api:digest-writer':duplicate},sources:[{id:f.plan.id,teamId:'team',parameters}]})).toThrow(); + const moved={...f.selected,purpose:'Changed after frozen selection.'}; + expect(()=>projectActiveWorkdays({teamId:'team',revision:1,profiles:{...profiles,'sdk:digest-writer':moved},sources:[{id:f.plan.id,teamId:'team',parameters}]})).toThrow(); + const original=projectActiveWorkdays({teamId:'team',revision:1,profiles,sources:[{id:f.plan.id,teamId:'team',parameters}]}),changed=projectActiveWorkdays({teamId:'team',revision:1,profiles,sources:[{id:f.plan.id,teamId:'team',parameters:{...parameters,appliedPlan:{...f.plan,reportingAgentId:f.other.id}}}]} ); + expect(changed.changedSourceRefs).not.toEqual(original.changedSourceRefs); + expect(changed.nodes.filter(node=>node.kind==='reporting').map(node=>node.projectId)).toEqual(['api']); +}); From 8be8217eb3a3ba2b1d3f78fa1df54d47ddb01f45 Mon Sep 17 00:00:00 2001 From: Adrian Webb Date: Sat, 17 Oct 2026 02:59:01 -0400 Subject: [PATCH 03/24] test: prove one reporting selection through original native public admission --- .../reporting-selection-native.test.ts | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting-selection-native.test.ts diff --git a/tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting-selection-native.test.ts b/tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting-selection-native.test.ts new file mode 100644 index 000000000..0f306f6a1 --- /dev/null +++ b/tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting-selection-native.test.ts @@ -0,0 +1,31 @@ +import {expect,it} from 'vitest'; +import {workdayStartDatabase} from './workday-start-fixture.ts'; + +it('native public preflight and start retain one configured joint Reporter before activation and preserve exact selection through denial and replay',async()=>{ + const f=await workdayStartDatabase();try{ + const selected={...f.definition,activityProfiles:{...f.definition.activityProfiles,reporting:{handler:'reporter',prompt:{system:'Commit the deterministic closeout.'},permissions:f.definition.activityProfiles.planning!.permissions,dependsOn:{events:['workday-closing']}}}},other={...selected,id:'other/renamed-planner'}; + const selectedBytes=JSON.stringify({agents:[selected]}),now=f.intent.startsAt; + await f.query('UPDATE project_agent_classes SET handler_refs_json=? WHERE id=?',[selectedBytes,'class']); + await f.query('INSERT INTO projects (id,team_id,slug,name,metadata_json,created_at,updated_at) VALUES (?,?,?,?,?,?,?)',['other','team','other','Other',JSON.stringify({library:{role:'library'}}),now,now]); + await f.query('INSERT INTO project_agent_classes (id,team_id,project_id,slug,name,handler_refs_json,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?)',['other-class','team','other','boundary-planner','Other configured planner',JSON.stringify({agents:[other]}),now,now]); + await f.query('INSERT INTO treedx_project_libraries (id,team_id,project_id,instance_id,library_id,repository_id,content_path,content_repository_default_branch,content_repository_ref,metadata_json,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)',['other-binding','team','other','instance','other-library','planning-library','.','staging','a'.repeat(40),JSON.stringify({resolvedRef:'a'.repeat(40)}),now,now]); + const input={...f.intent,projects:['project','other'],reportingAgentId:selected.id},held=structuredClone(input); + const planned=await f.publicService.preflight(f.principal,'team',input); + const receiptBefore=await f.snapshot(); + await f.query('UPDATE project_agent_classes SET handler_refs_json=? WHERE id=?',[JSON.stringify({agents:[{...selected,purpose:'Changed after original preflight.'}]}),'class']); + await expect(f.start(planned)).rejects.toThrow();expect(await f.snapshot()).toEqual(receiptBefore); + await f.query('UPDATE project_agent_classes SET handler_refs_json=? WHERE id=?',[selectedBytes,'class']); + const started=await f.start(planned),after=await f.snapshot(); + expect(after.workdays).toHaveLength(1); + const parameters=JSON.parse(String(after.workdays[0]!.parameters_json)); + expect.soft(parameters.appliedPlan).toMatchObject({state:'active',reportingAgentId:selected.id}); + expect.soft(after.nodes.filter(row=>row.kind==='reporting').map(row=>row.project_id)).toEqual(['project']); + expect(after.nodes.filter(row=>row.kind==='planning').map(row=>row.project_id).sort()).toEqual(['other','project']); + expect(await f.start(planned)).toEqual(started);expect(await f.snapshot()).toEqual(after); + expect(after.assignments).toEqual([]);expect(after.reservations).toEqual([]);expect(after.usage).toEqual([]);expect(after.ledger).toEqual([]);expect(input).toEqual(held); + for(const reportingAgentId of [undefined,'foreign/renamed-planner','missing']){ + const supplied={...input};delete supplied.reportingAgentId;Object.assign(supplied,reportingAgentId===undefined?{}:{reportingAgentId}); + const before=await f.snapshot();await expect(f.publicService.preflight(f.principal,'team',supplied)).rejects.toThrow();expect(await f.snapshot()).toEqual(before); + } + }finally{await f.close();} +},30_000); From 910feb212652be92726fbc2934b4b3e98de6dde9 Mon Sep 17 00:00:00 2001 From: Adrian Webb Date: Sat, 17 Oct 2026 02:59:46 -0400 Subject: [PATCH 04/24] fix: retain one governed reporting selection before workday activation --- .../execution/workday-execution-projector.ts | 24 +++++++++++-------- .../policy/execution/workday-participants.ts | 10 ++++++++ .../scheduling/workday-preflight-service.ts | 3 ++- .../scheduling/workday-scheduling-service.ts | 6 +++-- 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/src/api/capacity/policy/execution/workday-execution-projector.ts b/src/api/capacity/policy/execution/workday-execution-projector.ts index 1695e0f0c..d9ea4950e 100644 --- a/src/api/capacity/policy/execution/workday-execution-projector.ts +++ b/src/api/capacity/policy/execution/workday-execution-projector.ts @@ -1,7 +1,7 @@ import { createHash } from 'node:crypto'; import { appliedWorkdaySchema, executionEdgeSchema, executionNodeSchema, type AgentDefinition, type ExecutionEdge, type ExecutionNode, type ExactEntityReference } from '@treeseed/sdk/agent-capacity'; -import { workdayParticipants, type WorkdayParticipant } from './workday-participants.ts'; +import { workdayParticipants, selectWorkdayReportingAgent, type WorkdayParticipant } from './workday-participants.ts'; import { modelTurnEstimate } from './model-turn-estimate.ts'; type Row = Record; @@ -34,9 +34,10 @@ export interface ActiveWorkdayProjectionSource { } function sourceRef(workday: ReturnType): ExactEntityReference { - const { schemaVersion, id, teamId, executionMode, policyId, policyRevision, policySnapshot, startsAt, endsAt } = workday; + const { schemaVersion, id, teamId, executionMode, policyId, policyRevision, policySnapshot, startsAt, endsAt, reportingAgentId } = workday; return { store: 'postgresql', model: 'workday', id, revision: policyRevision, - digest: digest({ schemaVersion, id, teamId, executionMode, policyId, policyRevision, policySnapshot, startsAt, endsAt }) }; + digest: digest({ schemaVersion, id, teamId, executionMode, policyId, policyRevision, policySnapshot, startsAt, endsAt, + ...(reportingAgentId === undefined ? {} : { reportingAgentId }) }) }; } function edge(teamId: string, fromNodeId: string, toNodeId: string, provenance: ExecutionEdge['provenance'], @@ -172,13 +173,16 @@ export function projectActiveWorkdays(input: { teamId: string; revision: number; } } } - for (const projectId of projectIds) { - const candidates = Object.entries(input.profiles).filter(([key, definition]) => - key === `${projectId}:${definition.agentClass}` && definition.activityProfiles.reporting); - if (candidates.length > 1) throw new Error(`Ambiguous reporting profile selection for project ${projectId}.`); - const reporter = candidates[0]?.[1]; - const reporting = reporter?.activityProfiles.reporting; - if (!reporter || !reporting) continue; + const selectedReporter = selectWorkdayReportingAgent(Object.entries(input.profiles).flatMap(([key, definition]) => + projectIds.filter(projectId => key === `${projectId}:${definition.agentClass}`).map(projectId => ({ projectId, definition }))), workday.reportingAgentId); + if (selectedReporter) { + const { projectId, definition: reporter } = selectedReporter; + if (workday.reportingAgentId !== undefined) { + const frozen = array(record(record(source.parameters.agentProfilesByProjectId)[projectId]).agents) + .map(entry => record(entry).definition).filter(definition => text(record(definition).id) === workday.reportingAgentId); + if (frozen.length !== 1 || stable(frozen[0]) !== stable(reporter)) throw new Error('The selected reporting profile differs from its frozen Workday authority.'); + } + const reporting = reporter.activityProfiles.reporting!; const reporterId = `reporting:${workday.id}:${projectId}/${reporter.id}`; const report = executionNodeSchema.parse({ schemaVersion: 'treeseed.execution-node/v1', id: reporterId, teamId: input.teamId, projectId, workdayId: workday.id, kind: 'reporting', pairRole: null, diff --git a/src/api/capacity/policy/execution/workday-participants.ts b/src/api/capacity/policy/execution/workday-participants.ts index c04b35cb7..8bbc0432c 100644 --- a/src/api/capacity/policy/execution/workday-participants.ts +++ b/src/api/capacity/policy/execution/workday-participants.ts @@ -1,4 +1,5 @@ import { createHash } from 'node:crypto'; +import { CapacityGovernanceError } from '../../database.ts'; import { validateAgentDefinitionModel, type AgentDefinition } from '@treeseed/sdk/agent-capacity'; type Row = Record; @@ -62,3 +63,12 @@ export function workdayParticipants(parameters: Row): WorkdayParticipant[] { } return participants.sort((left, right) => left.id.localeCompare(right.id)); } + +/** Resolve one configured closeout profile without changing planning participation. */ +export function selectWorkdayReportingAgent(candidates: Array<{projectId: string; definition: AgentDefinition}>, selection?: unknown) { + const eligible=candidates.filter(candidate=>candidate.definition.activityProfiles.reporting); + const selected=selection===undefined?eligible:eligible.filter(candidate=>candidate.definition.id===selection); + if((selection!==undefined && selected.length!==1)||selected.length>1) throw new CapacityGovernanceError( + 'capacity_workday_reporting_selection_invalid','Select exactly one eligible configured reporting agent from the participating projects.',409); + return selected[0] ?? null; +} diff --git a/src/api/capacity/services/capacity/workdays/scheduling/workday-preflight-service.ts b/src/api/capacity/services/capacity/workdays/scheduling/workday-preflight-service.ts index 494853a12..2ddf5f58f 100644 --- a/src/api/capacity/services/capacity/workdays/scheduling/workday-preflight-service.ts +++ b/src/api/capacity/services/capacity/workdays/scheduling/workday-preflight-service.ts @@ -136,6 +136,7 @@ export class WorkdayPreflightService { profileId:intent.profileId,projectSlugs:intent.projects==='all'?[]:intent.projects, projects:intent.projects==='all'?[]:intent.projects,durationSeconds,maximumConcurrency:maxConcurrency, ...(intent.agentSelection?{agentSelection:intent.agentSelection}:{}), + ...(intent.reportingAgentId === undefined ? {} : { reportingAgentId:intent.reportingAgentId }), ...(intent.proposalIds?.length?{proposalIds:intent.proposalIds}:{}), ...(intent.decisionIds?.length?{decisionIds:intent.decisionIds}:{}), ...(intent.continueFromWorkdayId?{continueFromWorkdayId:intent.continueFromWorkdayId}:{}), @@ -209,7 +210,7 @@ export class WorkdayPreflightService { const appliedPlan=record(projection.appliedPlan); const profileGeneration=integer(appliedPlan.policyRevision,1); const state:WorkdayPreflightObservation={ - profileGeneration, profileDigest:digest({profileId:intent.profileId,policy:appliedPlan.policySnapshot, + profileGeneration, profileDigest:digest({profileId:intent.profileId,policy:appliedPlan.policySnapshot,reportingAgentId:appliedPlan.reportingAgentId, projects:(Array.isArray(projection.projects)?projection.projects.map(record):[]).map(project=>({ id:project.id,repositoryId:project.repositoryId,contentRevision:project.contentRevision,agentProfileRevision:project.agentProfileRevision, }))}), demandSetDigest:digest({selectedDemands,objectives:intent.objectiveFilters??[],proposalIds:intent.proposalIds??[],decisionIds:intent.decisionIds??[]}), diff --git a/src/api/capacity/services/capacity/workdays/scheduling/workday-scheduling-service.ts b/src/api/capacity/services/capacity/workdays/scheduling/workday-scheduling-service.ts index f0c09df4a..2bc8c4eae 100644 --- a/src/api/capacity/services/capacity/workdays/scheduling/workday-scheduling-service.ts +++ b/src/api/capacity/services/capacity/workdays/scheduling/workday-scheduling-service.ts @@ -13,7 +13,7 @@ type WorkdayProject, import { resolveWorkdayAgentProfileSnapshot } from '../policy/workday-agent-profile-policy.ts'; import { reconcileTreeDxRefSignals } from '../../../treedx/repositories/treedx-ref-signal-reconciler.ts'; import { reconcileCommunicationExecutionGraph, reconcileExecutionGraph } from '../../../../../control-plane/repositories/capacity/execution/execution-graph-service.ts'; -import { workdayParticipants } from '../../../../policy/execution/workday-participants.ts'; +import { workdayParticipants, selectWorkdayReportingAgent } from '../../../../policy/execution/workday-participants.ts'; import { readExactProposal } from '../../../../../governance/executable-proposal.ts'; type JsonRecord = Record; @@ -154,6 +154,8 @@ async function resolveCapacityWorkdayPreflight( proposalsByProjectId: Object.fromEntries(projects.map(project => [project.id, selectedProposals.filter(proposal => proposal.projectId === project.id).map(proposal => proposal.definition)])), }).map((participant) => participant.id); + const reportingAgent = selectWorkdayReportingAgent([...agentProfiles].flatMap(([projectId, snapshot]) => + snapshot.agents.map(({ definition }) => ({ projectId, definition }))), parameters.reportingAgentId); const appliedPlan = compileWorkday({ id: run.id, teamId: run.teamId, executionMode, activityTypes: Array.isArray(record(parameters.agentSelection).activityTypes) @@ -165,7 +167,7 @@ async function resolveCapacityWorkdayPreflight( planningTurnMaximumSeconds: Number(parameters.planningTurnMaximumSeconds ?? 180), communicationConcurrency: Math.max(1, Number(parameters.communicationConcurrency ?? 1)), ...canonicalWorkdayShares(parameters, projects) }, - agentIds, startsAt: startedAt }); + agentIds, startsAt: startedAt, ...(reportingAgent ? { reportingAgentId: reportingAgent.definition.id } : {}) }); // Turn ceilings are not reservations. Admission sizes each turn against supply. return { parameters,executionMode,providerId,startedAt,environment,membership,projects,contexts,proposalContexts,agentProfiles,time,appliedPlan }; } From b9b95f365d025ff1cbcb581319e5ba6b1921afd9 Mon Sep 17 00:00:00 2001 From: Adrian Webb Date: Sat, 17 Oct 2026 03:00:03 -0400 Subject: [PATCH 05/24] fix: retain reporting selection through the original public Workday boundary --- .../capacity/workdays/scheduling/workday-preflight-service.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/api/capacity/services/capacity/workdays/scheduling/workday-preflight-service.ts b/src/api/capacity/services/capacity/workdays/scheduling/workday-preflight-service.ts index 2ddf5f58f..e87de5f4e 100644 --- a/src/api/capacity/services/capacity/workdays/scheduling/workday-preflight-service.ts +++ b/src/api/capacity/services/capacity/workdays/scheduling/workday-preflight-service.ts @@ -37,7 +37,7 @@ function digest(value:unknown):string { return `sha256:${sha256(canonicalJson(va function diagnosticsError(code:string,message:string,diagnostics:unknown):never { throw new CapacityGovernanceError(code,message,400,{diagnostics}); } export function parsePublicWorkdayIntent(teamId:string,input:JsonRecord):WorkdayIntent { - const allowed=new Set(['schemaVersion','teamId','profileId','projects','executionMode','startsAt','endsAt','durationSeconds','objectiveFilters','planningOnly','proposalIds','decisionIds','continueFromWorkdayId','operatorConstraints','agentSelection','allocation']); + const allowed=new Set(['schemaVersion','teamId','profileId','projects','executionMode','startsAt','endsAt','durationSeconds','objectiveFilters','planningOnly','proposalIds','decisionIds','continueFromWorkdayId','operatorConstraints','agentSelection','allocation','reportingAgentId']); const forbidden=Object.keys(input).filter((key)=>!allowed.has(key)); if(forbidden.length) diagnosticsError('workday_intent_derived_fields_forbidden','Workday preflight accepts high-level intent only.',forbidden.map((path)=>({code:'field_forbidden',path}))); if(input.teamId!==undefined&&text(input.teamId)!==teamId) diagnosticsError('workday_intent_team_mismatch','Workday intent team must match the route team.',[{code:'team_mismatch',path:'teamId'}]); @@ -66,6 +66,7 @@ export function parsePublicWorkdayIntent(teamId:string,input:JsonRecord):Workday ...(Array.isArray(input.objectiveFilters)?{objectiveFilters:input.objectiveFilters.map(text).filter(Boolean)}:{}), ...(input.planningOnly!==undefined?{planningOnly:input.planningOnly as boolean}:{}), ...(input.continueFromWorkdayId!==undefined?{continueFromWorkdayId:input.continueFromWorkdayId as string}:{}), + ...(input.reportingAgentId!==undefined?{reportingAgentId:input.reportingAgentId as string}:{}), ...(Array.isArray(input.proposalIds)?{proposalIds:[...new Set(input.proposalIds.map(text).filter(Boolean))].sort()}:input.proposalIds!==undefined?{proposalIds:input.proposalIds as string[]}:{}), ...(Array.isArray(input.decisionIds)?{decisionIds:[...new Set(input.decisionIds.map(text).filter(Boolean))].sort()}:input.decisionIds!==undefined?{decisionIds:input.decisionIds as string[]}:{}), ...(agentSelection!==undefined?{agentSelection:agentSelection as WorkdayIntent['agentSelection']}:{}), From 4c398194cedb9ed62d4580cafb8f75d9f429b679 Mon Sep 17 00:00:00 2001 From: Adrian Webb Date: Sat, 17 Oct 2026 03:05:03 -0400 Subject: [PATCH 06/24] test: select canonical reporting admission proof in existing API scenes --- .../scenes/component-boundaries.scene.yaml | 12 +++++++++++ guarantees/verifiers/golden.verifiers.yaml | 20 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/guarantees/agent/golden/scenes/component-boundaries.scene.yaml b/guarantees/agent/golden/scenes/component-boundaries.scene.yaml index 470f4f85d..0df0fd5fd 100644 --- a/guarantees/agent/golden/scenes/component-boundaries.scene.yaml +++ b/guarantees/agent/golden/scenes/component-boundaries.scene.yaml @@ -2834,3 +2834,15 @@ workflow: - id: execution-retired-participation-2 action: { verifier: api.golden.execution-retired-participation-2 } expect: { status: passed } + - id: reporting-selection-plan + action: { verifier: api.golden.reporting-selection-plan } + expect: { status: passed } + - id: reporting-selection-projection + action: { verifier: api.golden.reporting-selection-projection } + expect: { status: passed } + - id: reporting-selection-denials + action: { verifier: api.golden.reporting-selection-denials } + expect: { status: passed } + - id: reporting-selection-native + action: { verifier: api.golden.reporting-selection-native } + expect: { status: passed } diff --git a/guarantees/verifiers/golden.verifiers.yaml b/guarantees/verifiers/golden.verifiers.yaml index 4761cc6dd..61c5d8986 100644 --- a/guarantees/verifiers/golden.verifiers.yaml +++ b/guarantees/verifiers/golden.verifiers.yaml @@ -4804,3 +4804,23 @@ verifiers: ownerPackage: "@treeseed/api" testFile: tests/unit/control-plane/capacity/execution/architecture/native-inventory.test.ts testName: "requires native absence of every retired table including source candidates without accepting ambiguous catalog or resolution results" + api.golden.reporting-selection-plan: + kind: vitestCase + ownerPackage: "@treeseed/api" + testFile: tests/unit/control-plane/capacity/execution/graph/workday-execution-projector.test.ts + testName: "retains one explicitly selected configured Reporter in the canonical applied Workday before activation without a second authority" + api.golden.reporting-selection-projection: + kind: vitestCase + ownerPackage: "@treeseed/api" + testFile: tests/unit/control-plane/capacity/execution/graph/workday-execution-projector.test.ts + testName: "projects only the selected configured closeout Reporter while preserving every participating project planning contributor" + api.golden.reporting-selection-denials: + kind: vitestCase + ownerPackage: "@treeseed/api" + testFile: tests/unit/control-plane/capacity/execution/graph/workday-execution-projector.test.ts + testName: "denies omitted ambiguous foreign duplicate and moved reporting authority without replacing the captured selection" + api.golden.reporting-selection-native: + kind: vitestCase + ownerPackage: "@treeseed/api" + testFile: tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting-selection-native.test.ts + testName: "native public preflight and start retain one configured joint Reporter before activation and preserve exact selection through denial and replay" From d8b880f90dbac0cd548486b6e0481a6860d34b15 Mon Sep 17 00:00:00 2001 From: Adrian Webb Date: Sat, 17 Oct 2026 03:05:31 -0400 Subject: [PATCH 07/24] test: deny malformed reporting selectors at the original public API boundary --- .../architecture/reporting-selection-native.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting-selection-native.test.ts b/tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting-selection-native.test.ts index 0f306f6a1..85ee93590 100644 --- a/tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting-selection-native.test.ts +++ b/tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting-selection-native.test.ts @@ -23,8 +23,8 @@ it('native public preflight and start retain one configured joint Reporter befor expect(after.nodes.filter(row=>row.kind==='planning').map(row=>row.project_id).sort()).toEqual(['other','project']); expect(await f.start(planned)).toEqual(started);expect(await f.snapshot()).toEqual(after); expect(after.assignments).toEqual([]);expect(after.reservations).toEqual([]);expect(after.usage).toEqual([]);expect(after.ledger).toEqual([]);expect(input).toEqual(held); - for(const reportingAgentId of [undefined,'foreign/renamed-planner','missing']){ - const supplied={...input};delete supplied.reportingAgentId;Object.assign(supplied,reportingAgentId===undefined?{}:{reportingAgentId}); + for(const reportingAgentId of [undefined,'foreign/renamed-planner','missing',null,'',' ',false,1,[],{},'é','id?','x'.repeat(201)]){ + const supplied:Record={...input};delete supplied.reportingAgentId;Object.assign(supplied,reportingAgentId===undefined?{}:{reportingAgentId}); const before=await f.snapshot();await expect(f.publicService.preflight(f.principal,'team',supplied)).rejects.toThrow();expect(await f.snapshot()).toEqual(before); } }finally{await f.close();} From ef5c62e4824462dcd82d4b5a5370b832e9d60c01 Mon Sep 17 00:00:00 2001 From: Adrian Webb Date: Sat, 17 Oct 2026 03:09:15 -0400 Subject: [PATCH 08/24] Keep reporting admission proof within its owning test directory bound Move the existing case intact; update only its relative fixture import and selected verifier path. All assertions and the complete suite remain enabled. --- guarantees/verifiers/golden.verifiers.yaml | 2 +- .../{ => reporting}/reporting-selection-native.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename tests/unit/control-plane/capacity/workdays/scheduling/architecture/{ => reporting}/reporting-selection-native.test.ts (98%) diff --git a/guarantees/verifiers/golden.verifiers.yaml b/guarantees/verifiers/golden.verifiers.yaml index 61c5d8986..72ef5b0f4 100644 --- a/guarantees/verifiers/golden.verifiers.yaml +++ b/guarantees/verifiers/golden.verifiers.yaml @@ -4822,5 +4822,5 @@ verifiers: api.golden.reporting-selection-native: kind: vitestCase ownerPackage: "@treeseed/api" - testFile: tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting-selection-native.test.ts + testFile: tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting/reporting-selection-native.test.ts testName: "native public preflight and start retain one configured joint Reporter before activation and preserve exact selection through denial and replay" diff --git a/tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting-selection-native.test.ts b/tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting/reporting-selection-native.test.ts similarity index 98% rename from tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting-selection-native.test.ts rename to tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting/reporting-selection-native.test.ts index 85ee93590..60e835f83 100644 --- a/tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting-selection-native.test.ts +++ b/tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting/reporting-selection-native.test.ts @@ -1,5 +1,5 @@ import {expect,it} from 'vitest'; -import {workdayStartDatabase} from './workday-start-fixture.ts'; +import {workdayStartDatabase} from '../workday-start-fixture.ts'; it('native public preflight and start retain one configured joint Reporter before activation and preserve exact selection through denial and replay',async()=>{ const f=await workdayStartDatabase();try{ From 277ac120faaf6dbe2edd89f5425674bef1397f8e Mon Sep 17 00:00:00 2001 From: Adrian Webb Date: Sat, 17 Oct 2026 03:12:02 -0400 Subject: [PATCH 09/24] test: retain the original automatic reporting choice through the admission boundary --- .../reporting-selection-native.test.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting/reporting-selection-native.test.ts b/tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting/reporting-selection-native.test.ts index 60e835f83..9b948502f 100644 --- a/tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting/reporting-selection-native.test.ts +++ b/tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting/reporting-selection-native.test.ts @@ -1,9 +1,11 @@ import {expect,it} from 'vitest'; +import type {AgentDefinition} from '@treeseed/sdk/agent-capacity'; import {workdayStartDatabase} from '../workday-start-fixture.ts'; +function configuredCloseout(definition:AgentDefinition):AgentDefinition{return {...definition,activityProfiles:{...definition.activityProfiles,reporting:{handler:'reporter',prompt:{system:'Commit the deterministic closeout.'},permissions:definition.activityProfiles.planning!.permissions,dependsOn:{events:['workday-closing']}}}};} it('native public preflight and start retain one configured joint Reporter before activation and preserve exact selection through denial and replay',async()=>{ const f=await workdayStartDatabase();try{ - const selected={...f.definition,activityProfiles:{...f.definition.activityProfiles,reporting:{handler:'reporter',prompt:{system:'Commit the deterministic closeout.'},permissions:f.definition.activityProfiles.planning!.permissions,dependsOn:{events:['workday-closing']}}}},other={...selected,id:'other/renamed-planner'}; + const selected=configuredCloseout(f.definition),other={...selected,id:'other/renamed-planner'}; const selectedBytes=JSON.stringify({agents:[selected]}),now=f.intent.startsAt; await f.query('UPDATE project_agent_classes SET handler_refs_json=? WHERE id=?',[selectedBytes,'class']); await f.query('INSERT INTO projects (id,team_id,slug,name,metadata_json,created_at,updated_at) VALUES (?,?,?,?,?,?,?)',['other','team','other','Other',JSON.stringify({library:{role:'library'}}),now,now]); @@ -29,3 +31,18 @@ it('native public preflight and start retain one configured joint Reporter befor } }finally{await f.close();} },30_000); + +it('native public start refuses a different automatic Reporter introduced after fresh preflight instead of silently changing the retained closeout identity',async()=>{ + const f=await workdayStartDatabase();try{ + const selected=configuredCloseout(f.definition),replacement={...selected,id:'configured/replacement-closeout'}; + await f.query('UPDATE project_agent_classes SET handler_refs_json=? WHERE id=?',[JSON.stringify({agents:[selected]}),'class']); + const planned=await f.preflight(),original=f.store.createCapacityWorkdayRun.bind(f.store);let calls=0; + f.store.createCapacityWorkdayRun=async(teamId,input)=>{ + calls++;await f.query('UPDATE project_agent_classes SET handler_refs_json=? WHERE id=?',[JSON.stringify({agents:[replacement]}),'class']); + return original(teamId,input); + }; + await expect(f.start(planned)).rejects.toThrow();expect(calls).toBe(1); + const after=await f.snapshot();expect(after.workdays.filter(row=>row.status==='running')).toEqual([]); + expect(after.nodes.filter(row=>row.kind==='reporting')).toEqual([]);expect(after.assignments).toEqual([]);expect(after.reservations).toEqual([]);expect(after.usage).toEqual([]);expect(after.ledger).toEqual([]); + }finally{await f.close();} +},30_000); From 0f7722863391cdcd3821a14d5579ee33c0c8a39d Mon Sep 17 00:00:00 2001 From: Adrian Webb Date: Sat, 17 Oct 2026 03:12:36 -0400 Subject: [PATCH 10/24] fix: retain the resolved reporting choice across original admission --- .../agent/golden/scenes/component-boundaries.scene.yaml | 3 +++ guarantees/verifiers/golden.verifiers.yaml | 5 +++++ .../workdays/scheduling/workday-preflight-service.ts | 2 ++ 3 files changed, 10 insertions(+) diff --git a/guarantees/agent/golden/scenes/component-boundaries.scene.yaml b/guarantees/agent/golden/scenes/component-boundaries.scene.yaml index 0df0fd5fd..f1fafda08 100644 --- a/guarantees/agent/golden/scenes/component-boundaries.scene.yaml +++ b/guarantees/agent/golden/scenes/component-boundaries.scene.yaml @@ -2846,3 +2846,6 @@ workflow: - id: reporting-selection-native action: { verifier: api.golden.reporting-selection-native } expect: { status: passed } + - id: reporting-selection-admission-seal-native + action: { verifier: api.golden.reporting-selection-admission-seal-native } + expect: { status: passed } diff --git a/guarantees/verifiers/golden.verifiers.yaml b/guarantees/verifiers/golden.verifiers.yaml index 72ef5b0f4..af36136dd 100644 --- a/guarantees/verifiers/golden.verifiers.yaml +++ b/guarantees/verifiers/golden.verifiers.yaml @@ -4824,3 +4824,8 @@ verifiers: ownerPackage: "@treeseed/api" testFile: tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting/reporting-selection-native.test.ts testName: "native public preflight and start retain one configured joint Reporter before activation and preserve exact selection through denial and replay" + api.golden.reporting-selection-admission-seal-native: + kind: vitestCase + ownerPackage: "@treeseed/api" + testFile: tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting/reporting-selection-native.test.ts + testName: "native public start refuses a different automatic Reporter introduced after fresh preflight instead of silently changing the retained closeout identity" diff --git a/src/api/capacity/services/capacity/workdays/scheduling/workday-preflight-service.ts b/src/api/capacity/services/capacity/workdays/scheduling/workday-preflight-service.ts index e87de5f4e..24ca3ea57 100644 --- a/src/api/capacity/services/capacity/workdays/scheduling/workday-preflight-service.ts +++ b/src/api/capacity/services/capacity/workdays/scheduling/workday-preflight-service.ts @@ -209,6 +209,8 @@ export class WorkdayPreflightService { allocatedSeconds:selectedDemands.filter((entry)=>entry.classSlug===classSlug).reduce((sum,entry)=>sum+entry.requestedSeconds,0), idleSeconds:0,reservedSeconds:0,activeSeconds:0,releasedSeconds:0,overrunSeconds:0})); const appliedPlan=record(projection.appliedPlan); + // Retain the resolved choice before creation can observe another configured profile. + if(appliedPlan.reportingAgentId!==undefined) record(runInput.parameters).reportingAgentId=appliedPlan.reportingAgentId; const profileGeneration=integer(appliedPlan.policyRevision,1); const state:WorkdayPreflightObservation={ profileGeneration, profileDigest:digest({profileId:intent.profileId,policy:appliedPlan.policySnapshot,reportingAgentId:appliedPlan.reportingAgentId, From f724fe5959a46735e05d382c855bf9ff08988649 Mon Sep 17 00:00:00 2001 From: Adrian Webb Date: Sat, 17 Oct 2026 03:14:38 -0400 Subject: [PATCH 11/24] test: read the retained reporting selection before native workday activation --- .../reporting/reporting-selection-native.test.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting/reporting-selection-native.test.ts b/tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting/reporting-selection-native.test.ts index 9b948502f..45422a348 100644 --- a/tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting/reporting-selection-native.test.ts +++ b/tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting/reporting-selection-native.test.ts @@ -14,6 +14,9 @@ it('native public preflight and start retain one configured joint Reporter befor const input={...f.intent,projects:['project','other'],reportingAgentId:selected.id},held=structuredClone(input); const planned=await f.publicService.preflight(f.principal,'team',input); const receiptBefore=await f.snapshot(); + expect(receiptBefore.workdays).toEqual([]); + const retained=JSON.parse(String(receiptBefore.receipts.find(row=>row.operation==='workday.preflight')!.response_json)); + expect(retained).toMatchObject({intent:{reportingAgentId:selected.id},runInput:{parameters:{reportingAgentId:selected.id}}}); await f.query('UPDATE project_agent_classes SET handler_refs_json=? WHERE id=?',[JSON.stringify({agents:[{...selected,purpose:'Changed after original preflight.'}]}),'class']); await expect(f.start(planned)).rejects.toThrow();expect(await f.snapshot()).toEqual(receiptBefore); await f.query('UPDATE project_agent_classes SET handler_refs_json=? WHERE id=?',[selectedBytes,'class']); @@ -37,12 +40,15 @@ it('native public start refuses a different automatic Reporter introduced after const selected=configuredCloseout(f.definition),replacement={...selected,id:'configured/replacement-closeout'}; await f.query('UPDATE project_agent_classes SET handler_refs_json=? WHERE id=?',[JSON.stringify({agents:[selected]}),'class']); const planned=await f.preflight(),original=f.store.createCapacityWorkdayRun.bind(f.store);let calls=0; + const before=await f.snapshot(),retained=JSON.parse(String(before.receipts.find(row=>row.operation==='workday.preflight')!.response_json)); + expect(before.workdays).toEqual([]);expect(retained.runInput.parameters.reportingAgentId).toBe(selected.id);expect(Object.hasOwn(retained.intent,'reportingAgentId')).toBe(false); f.store.createCapacityWorkdayRun=async(teamId,input)=>{ calls++;await f.query('UPDATE project_agent_classes SET handler_refs_json=? WHERE id=?',[JSON.stringify({agents:[replacement]}),'class']); return original(teamId,input); }; await expect(f.start(planned)).rejects.toThrow();expect(calls).toBe(1); const after=await f.snapshot();expect(after.workdays.filter(row=>row.status==='running')).toEqual([]); + expect(after.receipts.filter(row=>row.operation==='workday.preflight')).toEqual(before.receipts);expect(after.receipts.filter(row=>row.operation==='workday.start')).toEqual([]); expect(after.nodes.filter(row=>row.kind==='reporting')).toEqual([]);expect(after.assignments).toEqual([]);expect(after.reservations).toEqual([]);expect(after.usage).toEqual([]);expect(after.ledger).toEqual([]); }finally{await f.close();} },30_000); From 3f8bdac88c9abd001f844f5581b6f8e1525a2ae5 Mon Sep 17 00:00:00 2001 From: Adrian Webb Date: Sat, 17 Oct 2026 03:45:56 -0400 Subject: [PATCH 12/24] test: require closeout eligibility independently of cooperative planning selection --- .../capacity/planning/selection.test.ts | 7 ++++++ .../reporting-selection-native.test.ts | 24 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/tests/unit/control-plane/capacity/planning/selection.test.ts b/tests/unit/control-plane/capacity/planning/selection.test.ts index 2f0dbaf38..c87d6274b 100644 --- a/tests/unit/control-plane/capacity/planning/selection.test.ts +++ b/tests/unit/control-plane/capacity/planning/selection.test.ts @@ -32,3 +32,10 @@ describe('exact activity selection before living-node admission', () => { }); } }); + +it('retains one standing reporting activity beside an exact cooperative selection without changing selected planning work or admitting an empty intersection',()=>{ + const closeout=definition('closeout','digest-writer',{planning:profile('writer'),reporting:profile('reporter')}),rows=[...classes,{id:'class-c',slug:'digest-writer',status:'active',handlerRefs:{agents:[closeout]}}],held=structuredClone(rows); + const selected=compileWorkdayAgentProfileSnapshot(rows,{agentSlugs:['architect'],activityTypes:['planning']}); + expect(selected.agents.map(entry=>({id:entry.definition.id,activities:entry.activities}))).toEqual([{id:'sdk/architect',activities:['planning']},{id:'sdk/closeout',activities:['reporting']}]); + expect(()=>compileWorkdayAgentProfileSnapshot(rows,{agentSlugs:['architect'],activityTypes:['reviewing']})).toThrow(/no eligible/);expect(rows).toEqual(held); +}); diff --git a/tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting/reporting-selection-native.test.ts b/tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting/reporting-selection-native.test.ts index 45422a348..be2e48f1d 100644 --- a/tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting/reporting-selection-native.test.ts +++ b/tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting/reporting-selection-native.test.ts @@ -52,3 +52,27 @@ it('native public start refuses a different automatic Reporter introduced after expect(after.nodes.filter(row=>row.kind==='reporting')).toEqual([]);expect(after.assignments).toEqual([]);expect(after.reservations).toEqual([]);expect(after.usage).toEqual([]);expect(after.ledger).toEqual([]); }finally{await f.close();} },30_000); + +it('native public preflight denies a Workday with no configured closeout Reporter before any admission or receipt mutation',async()=>{ + const f=await workdayStartDatabase();try{ + const onlyPlanning=structuredClone(f.definition);Reflect.deleteProperty(onlyPlanning.activityProfiles,'reporting'); + await f.query('UPDATE project_agent_classes SET handler_refs_json=? WHERE id=?',[JSON.stringify({agents:[onlyPlanning]}),'class']); + const before=await f.snapshot();await expect(f.preflight()).rejects.toThrow();expect(await f.snapshot()).toEqual(before); + }finally{await f.close();} +},30_000); + +it('native public admission selects the configured closeout Reporter independently of cooperative planning filters without creating extra planning work',async()=>{ + const f=await workdayStartDatabase();try{ + const planner=structuredClone(f.definition);Reflect.deleteProperty(planner.activityProfiles,'reporting'); + const selected={...configuredCloseout(planner),id:'configured/standing-closeout',agentClass:'digest-writer'}; + await f.query('UPDATE project_agent_classes SET handler_refs_json=? WHERE id=?',[JSON.stringify({agents:[planner]}),'class']); + await f.query('INSERT INTO project_agent_classes (id,team_id,project_id,slug,name,handler_refs_json,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?)',['closeout-class','team','project','digest-writer','Configured closeout',JSON.stringify({agents:[selected]}),f.intent.startsAt,f.intent.startsAt]); + const input={...f.intent,reportingAgentId:selected.id,agentSelection:{agentSlugs:[planner.id],activityTypes:['planning']}},held=structuredClone(input); + const planned=await f.publicService.preflight(f.principal,'team',input);await f.start(planned); + const after=await f.snapshot(),parameters=JSON.parse(String(after.workdays[0]!.parameters_json)); + expect(parameters.appliedPlan.reportingAgentId).toBe(selected.id);expect(parameters.agentSelection).toEqual(input.agentSelection); + expect(parameters.agentProfilesByProjectId.project.agents.map((entry:{definition:{id:string};activities:string[]})=>({id:entry.definition.id,activities:entry.activities}))).toEqual([{id:planner.id,activities:['planning']},{id:selected.id,activities:['reporting']}]); + expect(after.nodes.filter(row=>row.kind==='planning').map(row=>row.agent_class)).toEqual([planner.agentClass]);expect(after.nodes.filter(row=>row.kind==='reporting').map(row=>row.agent_class)).toEqual([selected.agentClass]);expect(after.nodes.filter(row=>row.kind==='condition')).toHaveLength(1); + expect(after.assignments).toEqual([]);expect(after.reservations).toEqual([]);expect(after.usage).toEqual([]);expect(after.ledger).toEqual([]);expect(input).toEqual(held); + }finally{await f.close();} +},30_000); From dd32cdc603338af9710d60cdc6270caa0aa017db Mon Sep 17 00:00:00 2001 From: Adrian Webb Date: Sat, 17 Oct 2026 03:49:05 -0400 Subject: [PATCH 13/24] fix: reserve configured closeout eligibility independently of cooperative planning filters --- .../workdays/policy/workday-agent-profile-policy.ts | 8 ++++++++ .../workdays/scheduling/workday-scheduling-service.ts | 2 ++ .../scheduling/architecture/workday-start-fixture.ts | 5 +++++ .../scheduling/architecture/workday-start-native.test.ts | 5 ++++- 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/api/capacity/services/capacity/workdays/policy/workday-agent-profile-policy.ts b/src/api/capacity/services/capacity/workdays/policy/workday-agent-profile-policy.ts index 8d8444c48..a2af484a5 100644 --- a/src/api/capacity/services/capacity/workdays/policy/workday-agent-profile-policy.ts +++ b/src/api/capacity/services/capacity/workdays/policy/workday-agent-profile-policy.ts @@ -64,6 +64,14 @@ export function compileWorkdayAgentProfileSnapshot(agentClasses: unknown[], sele 'Workday selectors must identify eligible activity profiles exactly.', 409, { unknown }); if (!agents.length) throw new CapacityGovernanceError('capacity_workday_agent_selection_empty', 'Workday selection resolved no eligible activity profiles.', 409); + // Cooperative selectors cannot remove the standing closeout activity. + // Preserve the original empty/unknown selection denials before reserving it. + for (const entry of available) if (entry.definition.activityProfiles.reporting) { + const selected = agents.find(candidate => candidate.definition === entry.definition); + if (selected) { if (!selected.activities.includes('reporting')) selected.activities.push('reporting'); } + else agents.push({ ...entry, activities: ['reporting'] }); + } + agents.sort((left, right) => left.definition.id.localeCompare(right.definition.id)); const revision = createHash('sha256').update(stable(agents)).digest('hex'); return { revision, agents }; } diff --git a/src/api/capacity/services/capacity/workdays/scheduling/workday-scheduling-service.ts b/src/api/capacity/services/capacity/workdays/scheduling/workday-scheduling-service.ts index 2bc8c4eae..193932fd7 100644 --- a/src/api/capacity/services/capacity/workdays/scheduling/workday-scheduling-service.ts +++ b/src/api/capacity/services/capacity/workdays/scheduling/workday-scheduling-service.ts @@ -156,6 +156,8 @@ async function resolveCapacityWorkdayPreflight( }).map((participant) => participant.id); const reportingAgent = selectWorkdayReportingAgent([...agentProfiles].flatMap(([projectId, snapshot]) => snapshot.agents.map(({ definition }) => ({ projectId, definition }))), parameters.reportingAgentId); + if (run.executionKind === 'workday' && !reportingAgent) throw new CapacityGovernanceError( + 'capacity_workday_reporting_selection_invalid', 'A Workday requires one eligible configured closeout Reporter before activation.', 409); const appliedPlan = compileWorkday({ id: run.id, teamId: run.teamId, executionMode, activityTypes: Array.isArray(record(parameters.agentSelection).activityTypes) diff --git a/tests/unit/control-plane/capacity/workdays/scheduling/architecture/workday-start-fixture.ts b/tests/unit/control-plane/capacity/workdays/scheduling/architecture/workday-start-fixture.ts index 8729ee46a..16160a3cd 100644 --- a/tests/unit/control-plane/capacity/workdays/scheduling/architecture/workday-start-fixture.ts +++ b/tests/unit/control-plane/capacity/workdays/scheduling/architecture/workday-start-fixture.ts @@ -65,6 +65,11 @@ activityProfiles: handler: writer prompt: { system: Plan only the exact authorized subject. } permissions: { content: { read: [knowledge, proposal], write: [proposal] }, tools: [] } + reporting: + handler: reporter + prompt: { system: Commit the deterministic canonical Workday closeout. } + permissions: { content: { read: [knowledge, proposal], write: [note] }, tools: [] } + dependsOn: { events: [workday-closing] } `)); if (!parsed.ok || !parsed.data) throw new Error(JSON.stringify(parsed.diagnostics)); const definition = parsed.data; diff --git a/tests/unit/control-plane/capacity/workdays/scheduling/architecture/workday-start-native.test.ts b/tests/unit/control-plane/capacity/workdays/scheduling/architecture/workday-start-native.test.ts index b2af5b1d1..9093d28ad 100644 --- a/tests/unit/control-plane/capacity/workdays/scheduling/architecture/workday-start-native.test.ts +++ b/tests/unit/control-plane/capacity/workdays/scheduling/architecture/workday-start-native.test.ts @@ -283,7 +283,10 @@ describe('first manual and recurring admission through the same public owning pa expect(run.parameters.agentProfilesByProjectId).toMatchObject({ project: { agents: [{ definition: f.definition }] } }); expect(run.parameters.workdayContextByProjectId).toMatchObject({ project: { repository: 'planning-library', commit: 'a'.repeat(40), path: 'README.md' } }); expectNodeBirthHistory(truth);expect(expectWorkdayLifecycleHistory(truth)).toHaveLength(1); expect(truth.workdays).toHaveLength(1); expect(truth.nodes.length).toBeGreaterThan(0); - for (const node of truth.nodes) expect(node).toMatchObject({ team_id: 'team', project_id: 'project', workday_id: receipt.workdayId, kind: 'planning', agent_class: f.definition.agentClass }); + expect(truth.nodes.map(node=>node.kind).sort()).toEqual(['condition','planning','reporting']); + for (const node of truth.nodes) expect(node).toMatchObject({ team_id: 'team', project_id: 'project', workday_id: receipt.workdayId }); + for (const node of truth.nodes.filter(node=>node.kind!=='condition')) expect(node.agent_class).toBe(f.definition.agentClass); + expect(truth.nodes.filter(node=>node.kind==='reporting'||node.kind==='condition').every(node=>node.status==='blocked')).toBe(true); expect(truth.events.filter(event=>event.event_type!=='execution.node.state').map(event => event.event_type)).toEqual(['workday.started', 'workday.lifecycle.changed', 'assignment.polling_ready']); expect(truth.assignments).toEqual([]); expect(truth.reservations).toEqual([]); expect(truth.usage).toEqual([]); expect(truth.ledger).toEqual([]); expect(f.calls).toEqual([{ method: 'POST', path: '/api/v1/repos/planning-library/paths/list', From d871c481185a2c6fbcc92dff4931ab66613b9641 Mon Sep 17 00:00:00 2001 From: Adrian Webb Date: Sat, 17 Oct 2026 03:54:16 -0400 Subject: [PATCH 14/24] test: retain exact planning and blocked closeout birth history with original selected authority --- .../workdays/scheduling/workday-scheduling-service.ts | 6 +++--- .../workdays/scheduling/architecture/node-birth-history.ts | 6 +++--- .../reporting/reporting-selection-native.test.ts | 3 ++- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/api/capacity/services/capacity/workdays/scheduling/workday-scheduling-service.ts b/src/api/capacity/services/capacity/workdays/scheduling/workday-scheduling-service.ts index 193932fd7..575afab54 100644 --- a/src/api/capacity/services/capacity/workdays/scheduling/workday-scheduling-service.ts +++ b/src/api/capacity/services/capacity/workdays/scheduling/workday-scheduling-service.ts @@ -154,8 +154,8 @@ async function resolveCapacityWorkdayPreflight( proposalsByProjectId: Object.fromEntries(projects.map(project => [project.id, selectedProposals.filter(proposal => proposal.projectId === project.id).map(proposal => proposal.definition)])), }).map((participant) => participant.id); - const reportingAgent = selectWorkdayReportingAgent([...agentProfiles].flatMap(([projectId, snapshot]) => - snapshot.agents.map(({ definition }) => ({ projectId, definition }))), parameters.reportingAgentId); + const reportingAgent = run.executionKind === 'workday' ? selectWorkdayReportingAgent([...agentProfiles].flatMap(([projectId, snapshot]) => + snapshot.agents.map(({ definition }) => ({ projectId, definition }))), parameters.reportingAgentId) : null; if (run.executionKind === 'workday' && !reportingAgent) throw new CapacityGovernanceError( 'capacity_workday_reporting_selection_invalid', 'A Workday requires one eligible configured closeout Reporter before activation.', 409); const appliedPlan = compileWorkday({ id: run.id, teamId: run.teamId, @@ -228,7 +228,7 @@ export async function scheduleCapacityWorkdayRun( } const updated = await store.updateCapacityWorkdayRun(run.teamId, run.id, { parameters: { - ...parameters, appliedPlan: { ...appliedPlan, state: 'active', activatedAt: startedAt }, + ...parameters, ...(appliedPlan.reportingAgentId === undefined ? {} : { reportingAgentId:appliedPlan.reportingAgentId }), appliedPlan: { ...appliedPlan, state: 'active', activatedAt: startedAt }, availableSeconds: time.availableSeconds, scheduledProjectIds: projects.map((project) => project.id), scheduledProjectSlugs: projects.map((project) => project.slug ?? project.id), diff --git a/tests/unit/control-plane/capacity/workdays/scheduling/architecture/node-birth-history.ts b/tests/unit/control-plane/capacity/workdays/scheduling/architecture/node-birth-history.ts index 6f0f36e03..0632bcd0e 100644 --- a/tests/unit/control-plane/capacity/workdays/scheduling/architecture/node-birth-history.ts +++ b/tests/unit/control-plane/capacity/workdays/scheduling/architecture/node-birth-history.ts @@ -3,11 +3,11 @@ import{canonicalStandardsJson}from'@treeseed/sdk/standards'; import{appliedWorkdaySchema,compileWorkday}from'@treeseed/sdk/agent-capacity'; import{expect}from'vitest'; -/** These controlled native fixtures create ready planning nodes; direct SQL completion inputs do not manufacture history. */ +/** These controlled native fixtures create ready planning and blocked closeout nodes; direct SQL completion inputs do not manufacture history. */ export function expectNodeBirthHistory(snapshot:{nodes:Record[];events:Record[]}){ const births=snapshot.events.filter(event=>event.event_type==='execution.node.state'&&JSON.parse(String(event.context_json)).previousStatus===null); expect(births).toHaveLength(snapshot.nodes.length);expect(new Set(births.map(event=>JSON.parse(String(event.context_json)).nodeId)).size).toBe(snapshot.nodes.length); - for(const node of snapshot.nodes){const events=births.filter(event=>JSON.parse(String(event.context_json)).nodeId===node.id);expect(events).toHaveLength(1);const event=events[0]!;expect(event).toMatchObject({team_id:node.team_id,project_id:node.project_id,run_id:node.workday_id,workday_id:node.workday_id,assignment_id:null,status:'recorded'});expect(JSON.parse(String(event.context_json))).toEqual({nodeId:node.id,nodeRevision:node.node_revision,graphRevision:node.graph_revision_created,status:'ready',previousStatus:null});} + for(const node of snapshot.nodes){const expectedStatus=node.kind==='condition'||node.kind==='reporting'?'blocked':'ready';expect(node.status).toBe(expectedStatus);const events=births.filter(event=>JSON.parse(String(event.context_json)).nodeId===node.id);expect(events).toHaveLength(1);const event=events[0]!;expect(event).toMatchObject({team_id:node.team_id,project_id:node.project_id,run_id:node.workday_id,workday_id:node.workday_id,assignment_id:null,status:'recorded'});expect(JSON.parse(String(event.context_json))).toEqual({nodeId:node.id,nodeRevision:node.node_revision,graphRevision:node.graph_revision_created,status:expectedStatus,previousStatus:null});} } /** Independent native rows must retain the exact old/new canonical plan; no status or exit code substitutes for an observation. */ export function expectWorkdayLifecycleHistory(snapshot:{workdays:Record[];events:Record[]}){ @@ -17,7 +17,7 @@ export function expectWorkdayLifecycleHistory(snapshot:{workdays:Recordvalue!==null))expect(plan).toMatchObject({id:run.id,teamId:run.team_id,executionMode:run.execution_mode}); - if(before){for(const field of['id','teamId','executionMode','startsAt','endsAt','policyId','policyRevision','policySnapshot'])expect(Reflect.get(after,field)).toEqual(Reflect.get(before,field));}else{expect(prior).toBeUndefined();expect(after.state).toBe('active');expect(Date.parse(String(after.activatedAt))).toBe(Date.parse(after.startsAt));const prefix='planning:'+after.id+':1:',agentIds=after.planningRounds.flatMap(round=>round.assignmentIds.map(id=>{expect(id.startsWith(prefix)&&id.length>prefix.length).toBe(true);return id.slice(prefix.length);}));const compiled=compileWorkday({id:after.id,teamId:after.teamId,executionMode:after.executionMode,policyId:after.policyId,policyRevision:after.policyRevision,policy:after.policySnapshot,startsAt:after.startsAt,agentIds});expect({...after,admittedSecondsByProject:{},admittedSecondsByAgentClass:{}}).toEqual({...compiled,state:'active',activatedAt:after.activatedAt});for(const field of ['closingAt','endedAt','reportRef'])expect(Reflect.get(after,field)).toBeUndefined();} + if(before){for(const field of['id','teamId','executionMode','startsAt','endsAt','policyId','policyRevision','policySnapshot','reportingAgentId'])expect(Reflect.get(after,field)).toEqual(Reflect.get(before,field));}else{expect(prior).toBeUndefined();expect(after.state).toBe('active');expect(Date.parse(String(after.activatedAt))).toBe(Date.parse(after.startsAt));const prefix='planning:'+after.id+':1:',agentIds=after.planningRounds.flatMap(round=>round.assignmentIds.map(id=>{expect(id.startsWith(prefix)&&id.length>prefix.length).toBe(true);return id.slice(prefix.length);}));const compiled=compileWorkday({id:after.id,teamId:after.teamId,executionMode:after.executionMode,policyId:after.policyId,policyRevision:after.policyRevision,policy:after.policySnapshot,startsAt:after.startsAt,agentIds,reportingAgentId:after.reportingAgentId});expect({...after,admittedSecondsByProject:{},admittedSecondsByAgentClass:{}}).toEqual({...compiled,state:'active',activatedAt:after.activatedAt});for(const field of ['closingAt','endedAt','reportRef'])expect(Reflect.get(after,field)).toBeUndefined();} if(prior!==undefined){expect(before).toEqual(prior);expect(context.previousStatus).toBe(priorStatus);}expect(Number.isFinite(Date.parse(String(event.created_at)))).toBe(true);prior=after;priorStatus=context.status;found.push(event); } expect(prior).toEqual(appliedWorkdaySchema.parse(JSON.parse(String(run.parameters_json)).appliedPlan));expect(priorStatus).toBe(run.status); diff --git a/tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting/reporting-selection-native.test.ts b/tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting/reporting-selection-native.test.ts index be2e48f1d..3ae08a6f7 100644 --- a/tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting/reporting-selection-native.test.ts +++ b/tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting/reporting-selection-native.test.ts @@ -1,4 +1,5 @@ import {expect,it} from 'vitest'; +import {normalizeWorkdayAgentSelection} from '@treeseed/sdk/operator-contracts'; import type {AgentDefinition} from '@treeseed/sdk/agent-capacity'; import {workdayStartDatabase} from '../workday-start-fixture.ts'; function configuredCloseout(definition:AgentDefinition):AgentDefinition{return {...definition,activityProfiles:{...definition.activityProfiles,reporting:{handler:'reporter',prompt:{system:'Commit the deterministic closeout.'},permissions:definition.activityProfiles.planning!.permissions,dependsOn:{events:['workday-closing']}}}};} @@ -70,7 +71,7 @@ it('native public admission selects the configured closeout Reporter independent const input={...f.intent,reportingAgentId:selected.id,agentSelection:{agentSlugs:[planner.id],activityTypes:['planning']}},held=structuredClone(input); const planned=await f.publicService.preflight(f.principal,'team',input);await f.start(planned); const after=await f.snapshot(),parameters=JSON.parse(String(after.workdays[0]!.parameters_json)); - expect(parameters.appliedPlan.reportingAgentId).toBe(selected.id);expect(parameters.agentSelection).toEqual(input.agentSelection); + expect(parameters.appliedPlan.reportingAgentId).toBe(selected.id);expect(parameters.agentSelection).toEqual(normalizeWorkdayAgentSelection(input.agentSelection));expect(parameters.agentSelection.agentSlugs).toEqual(input.agentSelection.agentSlugs);expect(parameters.agentSelection.activityTypes).toEqual(input.agentSelection.activityTypes); expect(parameters.agentProfilesByProjectId.project.agents.map((entry:{definition:{id:string};activities:string[]})=>({id:entry.definition.id,activities:entry.activities}))).toEqual([{id:planner.id,activities:['planning']},{id:selected.id,activities:['reporting']}]); expect(after.nodes.filter(row=>row.kind==='planning').map(row=>row.agent_class)).toEqual([planner.agentClass]);expect(after.nodes.filter(row=>row.kind==='reporting').map(row=>row.agent_class)).toEqual([selected.agentClass]);expect(after.nodes.filter(row=>row.kind==='condition')).toHaveLength(1); expect(after.assignments).toEqual([]);expect(after.reservations).toEqual([]);expect(after.usage).toEqual([]);expect(after.ledger).toEqual([]);expect(input).toEqual(held); From bd222bbf8b111dcd242f842215d2eded751880e9 Mon Sep 17 00:00:00 2001 From: Adrian Webb Date: Sat, 17 Oct 2026 03:56:22 -0400 Subject: [PATCH 15/24] test: select closeout eligibility and independent planning-filter proof in existing API scenes --- .../golden/scenes/component-boundaries.scene.yaml | 9 +++++++++ guarantees/verifiers/golden.verifiers.yaml | 15 +++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/guarantees/agent/golden/scenes/component-boundaries.scene.yaml b/guarantees/agent/golden/scenes/component-boundaries.scene.yaml index f1fafda08..9061a3303 100644 --- a/guarantees/agent/golden/scenes/component-boundaries.scene.yaml +++ b/guarantees/agent/golden/scenes/component-boundaries.scene.yaml @@ -2849,3 +2849,12 @@ workflow: - id: reporting-selection-admission-seal-native action: { verifier: api.golden.reporting-selection-admission-seal-native } expect: { status: passed } + - id: reporting-eligibility-required-native + action: { verifier: api.golden.reporting-eligibility-required-native } + expect: { status: passed } + - id: reporting-selection-cooperative-native + action: { verifier: api.golden.reporting-selection-cooperative-native } + expect: { status: passed } + - id: reporting-selection-cooperative-unit + action: { verifier: api.golden.reporting-selection-cooperative-unit } + expect: { status: passed } diff --git a/guarantees/verifiers/golden.verifiers.yaml b/guarantees/verifiers/golden.verifiers.yaml index af36136dd..1b339bbce 100644 --- a/guarantees/verifiers/golden.verifiers.yaml +++ b/guarantees/verifiers/golden.verifiers.yaml @@ -4829,3 +4829,18 @@ verifiers: ownerPackage: "@treeseed/api" testFile: tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting/reporting-selection-native.test.ts testName: "native public start refuses a different automatic Reporter introduced after fresh preflight instead of silently changing the retained closeout identity" + api.golden.reporting-eligibility-required-native: + kind: vitestCase + ownerPackage: "@treeseed/api" + testFile: tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting/reporting-selection-native.test.ts + testName: "native public preflight denies a Workday with no configured closeout Reporter before any admission or receipt mutation" + api.golden.reporting-selection-cooperative-native: + kind: vitestCase + ownerPackage: "@treeseed/api" + testFile: tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting/reporting-selection-native.test.ts + testName: "native public admission selects the configured closeout Reporter independently of cooperative planning filters without creating extra planning work" + api.golden.reporting-selection-cooperative-unit: + kind: vitestCase + ownerPackage: "@treeseed/api" + testFile: tests/unit/control-plane/capacity/planning/selection.test.ts + testName: "retains one standing reporting activity beside an exact cooperative selection without changing selected planning work or admitting an empty intersection" From af0b2bd66449891e41b5d0038483eeb3960ef8c6 Mon Sep 17 00:00:00 2001 From: Adrian Webb Date: Sat, 17 Oct 2026 04:07:27 -0400 Subject: [PATCH 16/24] build: adopt the checked canonical Reporter SDK archive and exact dependency lock --- .github/workflows/verify.yml | 2 +- package-lock.json | 6 +++--- package.json | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index 3095569e7..dacd1d074 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -70,7 +70,7 @@ jobs: - name: Build the verified native TreeDX engine working-directory: .treeseed/tools/treedx/apps/api run: MIX_ENV=dev mix compile - - uses: treeseed-ai/sdk/.github/actions/install-exact-sdk@952195376b53bf39742e64f320f2a3b109cc77c0 + - uses: treeseed-ai/sdk/.github/actions/install-exact-sdk@53bdc4d1deeeb78ce8c54a96539f311b2ac361ae env: NODE_ENV: production with: diff --git a/package-lock.json b/package-lock.json index 0baa601ba..5cd82bab1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "@react-email/render": "^2.0.8", "@treeseed/deployment": "https://github.com/treeseed-ai/deployment/releases/download/0.1.0-rc.321/treeseed-deployment-runtime-0.1.0-rc.321.tgz", "@treeseed/identity": "0.1.0-rc.19", - "@treeseed/sdk": "git+https://github.com/treeseed-ai/sdk.git#952195376b53bf39742e64f320f2a3b109cc77c0", + "@treeseed/sdk": "git+https://github.com/treeseed-ai/sdk.git#53bdc4d1deeeb78ce8c54a96539f311b2ac361ae", "@treeseed/treedx": "0.3.0-rc.18", "drizzle-orm": "^0.45.2", "hono": "4.13.3", @@ -1935,8 +1935,8 @@ }, "node_modules/@treeseed/sdk": { "version": "0.13.0-rc.122", - "resolved": "git+ssh://git@github.com/treeseed-ai/sdk.git#952195376b53bf39742e64f320f2a3b109cc77c0", - "integrity": "sha512-y57GDMPs1sfmwykNyVCQ9NDjqbIEImSxcF2F1BeF3xzVmOb+B2jd7E1tx9ZypQ8w0EXS4wjhb+XpSyxn+B/+MQ==", + "resolved": "git+ssh://git@github.com/treeseed-ai/sdk.git#53bdc4d1deeeb78ce8c54a96539f311b2ac361ae", + "integrity": "sha512-zk6dwa2JppPbhVxkq9ToXXN4QpOClXafPFqZ5/EHYWm95dOrYgxf3CLmVSWJsF4zhtt/pZ4TbDtZdZjc8Ads6w==", "license": "Apache-2.0", "dependencies": { "@treeseed/treedx": "0.3.0-rc.17", diff --git a/package.json b/package.json index a29ea3c00..c32709d56 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "@react-email/render": "^2.0.8", "@treeseed/deployment": "https://github.com/treeseed-ai/deployment/releases/download/0.1.0-rc.321/treeseed-deployment-runtime-0.1.0-rc.321.tgz", "@treeseed/identity": "0.1.0-rc.19", - "@treeseed/sdk": "git+https://github.com/treeseed-ai/sdk.git#952195376b53bf39742e64f320f2a3b109cc77c0", + "@treeseed/sdk": "git+https://github.com/treeseed-ai/sdk.git#53bdc4d1deeeb78ce8c54a96539f311b2ac361ae", "@treeseed/treedx": "0.3.0-rc.18", "drizzle-orm": "^0.45.2", "hono": "4.13.3", From 4e3a9528561e3e8ffaca4320b57e8039b8569f8d Mon Sep 17 00:00:00 2001 From: Adrian Webb Date: Sat, 17 Oct 2026 04:18:07 -0400 Subject: [PATCH 17/24] test: retain the selected joint Reporter through the original public schedule boundary --- .../reporting/reporting-selection-native.test.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting/reporting-selection-native.test.ts b/tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting/reporting-selection-native.test.ts index 3ae08a6f7..604a63f16 100644 --- a/tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting/reporting-selection-native.test.ts +++ b/tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting/reporting-selection-native.test.ts @@ -33,6 +33,11 @@ it('native public preflight and start retain one configured joint Reporter befor const supplied:Record={...input};delete supplied.reportingAgentId;Object.assign(supplied,reportingAgentId===undefined?{}:{reportingAgentId}); const before=await f.snapshot();await expect(f.publicService.preflight(f.principal,'team',supplied)).rejects.toThrow();expect(await f.snapshot()).toEqual(before); } + const beforeSchedule=await f.snapshot(),scheduledInput={id:'joint-closeout-selection',intent:input,cadenceSeconds:60,nextRunAt:input.startsAt},scheduledHeld=structuredClone(scheduledInput); + const scheduled=await f.publicService.createSchedule(f.principal,'team',scheduledInput); + expect(scheduled.intent.reportingAgentId).toBe(selected.id);expect(scheduled.intent.projects).toEqual(['other','project']);expect(scheduledInput).toEqual(scheduledHeld); + const afterSchedule=await f.snapshot();expect(afterSchedule.schedules).toHaveLength(1);expect(JSON.parse(String(afterSchedule.schedules[0]!.intent_json)).reportingAgentId).toBe(selected.id); + for(const table of ['workdays','nodes','edges','revisions','events','assignments','reservations','usage','ledger'] as const)expect(afterSchedule[table]).toEqual(beforeSchedule[table]); }finally{await f.close();} },30_000); From b4736c05db7dbe4e4a9b005ee29cf71f7f198a48 Mon Sep 17 00:00:00 2001 From: Adrian Webb Date: Sat, 17 Oct 2026 04:20:03 -0400 Subject: [PATCH 18/24] test: require exact original project ordering in retained schedule intent --- .../architecture/reporting/reporting-selection-native.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting/reporting-selection-native.test.ts b/tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting/reporting-selection-native.test.ts index 604a63f16..eb3a2bdab 100644 --- a/tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting/reporting-selection-native.test.ts +++ b/tests/unit/control-plane/capacity/workdays/scheduling/architecture/reporting/reporting-selection-native.test.ts @@ -35,7 +35,7 @@ it('native public preflight and start retain one configured joint Reporter befor } const beforeSchedule=await f.snapshot(),scheduledInput={id:'joint-closeout-selection',intent:input,cadenceSeconds:60,nextRunAt:input.startsAt},scheduledHeld=structuredClone(scheduledInput); const scheduled=await f.publicService.createSchedule(f.principal,'team',scheduledInput); - expect(scheduled.intent.reportingAgentId).toBe(selected.id);expect(scheduled.intent.projects).toEqual(['other','project']);expect(scheduledInput).toEqual(scheduledHeld); + expect(scheduled.intent.reportingAgentId).toBe(selected.id);expect(scheduled.intent.projects).toEqual(input.projects);expect(scheduledInput).toEqual(scheduledHeld); const afterSchedule=await f.snapshot();expect(afterSchedule.schedules).toHaveLength(1);expect(JSON.parse(String(afterSchedule.schedules[0]!.intent_json)).reportingAgentId).toBe(selected.id); for(const table of ['workdays','nodes','edges','revisions','events','assignments','reservations','usage','ledger'] as const)expect(afterSchedule[table]).toEqual(beforeSchedule[table]); }finally{await f.close();} From 41562e74ec4f3e505b031441be7c7f650b2ea6f6 Mon Sep 17 00:00:00 2001 From: Adrian Webb Date: Sat, 17 Oct 2026 04:35:50 -0400 Subject: [PATCH 19/24] test: retain immutable births and selected closeout readiness through native planning history --- .../workday-node-history-native.test.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/tests/unit/control-plane/capacity/workdays/scheduling/architecture/workday-node-history-native.test.ts b/tests/unit/control-plane/capacity/workdays/scheduling/architecture/workday-node-history-native.test.ts index 12976799f..55b903cbb 100644 --- a/tests/unit/control-plane/capacity/workdays/scheduling/architecture/workday-node-history-native.test.ts +++ b/tests/unit/control-plane/capacity/workdays/scheduling/architecture/workday-node-history-native.test.ts @@ -16,6 +16,7 @@ import{expectNodeBirthHistory,expectWorkdayLifecycleHistory}from'./node-birth-hi const initial = await f.store.getCapacityWorkdayRun('team', receipt.workdayId); if (!initial) throw new Error('Original native started run required'); const originalPlan = appliedWorkdaySchema.parse(initial.parameters.appliedPlan), initialTruth = await f.snapshot(); + const standingIds=initialTruth.nodes.filter(node=>node.kind!=='planning').map(node=>node.id);expect(initialTruth.nodes.map(node=>node.kind).sort()).toEqual(['condition','planning','reporting']);expect(standingIds).toHaveLength(2);expect(originalPlan.reportingAgentId).toBe(f.definition.id); expect(originalPlan.policySnapshot).toEqual(policy); expect(originalPlan.planningRounds).toHaveLength(1); const nativePlan = async () => { const run = await f.store.getCapacityWorkdayRun('team', receipt.workdayId); @@ -53,7 +54,7 @@ import{expectNodeBirthHistory,expectWorkdayLifecycleHistory}from'./node-birth-hi expect(next.startsAt).toBe(originalPlan.startsAt); expect(next.endsAt).toBe(originalPlan.endsAt); expect(next.policyRevision).toBe(originalPlan.policyRevision); expect(next.policySnapshot).toEqual(originalPlan.policySnapshot); const ids = next.planningRounds.flatMap(round => round.assignmentIds); - expect(new Set(ids).size).toBe(ids.length); expect(held.nodes.map(node => node.id).sort()).toEqual([...ids].sort()); + expect(new Set(ids).size).toBe(ids.length); expect(held.nodes.map(node => node.id).sort()).toEqual([...ids,...standingIds].sort()); const newest = next.planningRounds.at(-1)!; for (const id of newest.assignmentIds) { expect(held.nodes.find(node => node.id === id)).toMatchObject({ status: 'ready', kind: 'planning', workday_id: receipt.workdayId, @@ -77,18 +78,19 @@ import{expectNodeBirthHistory,expectWorkdayLifecycleHistory}from'./node-birth-hi await f.store.tickCapacityWorkdayRun('team', receipt.workdayId, originalPlan.endsAt, 'native-planning-expiry'); expect(await nativePlan()).toMatchObject({ state: 'closing', endsAt: originalPlan.endsAt, planningRounds: expect.arrayContaining([expect.objectContaining({ round: 4 })]) }); expect((await nativePlan()).planningRounds).toHaveLength(4); expect(f.intent).toEqual(input); - const final = await f.snapshot(); expect(final.usage).toEqual([]); expect(final.ledger).toEqual([]); + const final = await f.snapshot(); expect(final.usage).toEqual([]); expect(final.ledger).toEqual([]);expect(final.nodes.filter(node=>node.kind==='condition').map(node=>node.status)).toEqual(['completed']);expect(final.nodes.filter(node=>node.kind==='reporting').map(node=>node.status)).toEqual(['ready']);expect((await nativePlan()).reportingAgentId).toBe(originalPlan.reportingAgentId); } finally { await f.close(); } }); it('original native planning closeout observes every unclaimed cancellation before exact tick replay without changing the original deadline or financial authority',async()=>{ const f=await workdayStartDatabase();try{ const planned=await f.preflight(),started=await f.start(planned),run=await f.store.getCapacityWorkdayRun('team',started.workdayId);if(!run)throw new Error('Original native workday required'); - const plan=appliedWorkdaySchema.parse(run.parameters.appliedPlan),before=await f.snapshot();expectNodeBirthHistory(before);expect(before.nodes.length).toBeGreaterThan(0);expect(before.nodes.every(node=>node.status==='ready'&&node.kind==='planning')).toBe(true); + const plan=appliedWorkdaySchema.parse(run.parameters.appliedPlan),before=await f.snapshot();expectNodeBirthHistory(before);expect(before.nodes.length).toBeGreaterThan(0);expect(before.nodes.map(node=>node.kind).sort()).toEqual(['condition','planning','reporting']);expect(before.nodes.every(node=>node.status===(node.kind==='planning'?'ready':'blocked'))).toBe(true);const planning=before.nodes.filter(node=>node.kind==='planning');expect(planning).toHaveLength(1);expect(plan.reportingAgentId).toBe(f.definition.id); const tick=await f.store.tickCapacityWorkdayRun('team',started.workdayId,plan.endsAt,'native-node-closeout'),after=await f.snapshot(); - expect(after.nodes.map(node=>node.id).sort()).toEqual(before.nodes.map(node=>node.id).sort());expect(after.nodes.every(node=>node.status==='cancelled')).toBe(true);expectNodeBirthHistory(after); - const cancelled=after.events.filter(event=>event.event_type==='execution.node.state'&&JSON.parse(String(event.context_json)).status==='cancelled');expect(cancelled).toHaveLength(before.nodes.length); - for(const node of before.nodes){const observations=cancelled.filter(event=>JSON.parse(String(event.context_json)).nodeId===node.id);expect(observations).toHaveLength(1);expect(JSON.parse(String(observations[0]!.context_json))).toMatchObject({nodeId:node.id,nodeRevision:node.node_revision,status:'cancelled',previousStatus:node.status});} + expect(after.nodes.map(node=>node.id).sort()).toEqual(before.nodes.map(node=>node.id).sort());expect(after.nodes.every(node=>node.status===(node.kind==='planning'?'cancelled':node.kind==='condition'?'completed':'ready'))).toBe(true);expectNodeBirthHistory(after); + const cancelled=after.events.filter(event=>event.event_type==='execution.node.state'&&JSON.parse(String(event.context_json)).status==='cancelled');expect(cancelled).toHaveLength(planning.length); + for(const node of planning){const observations=cancelled.filter(event=>JSON.parse(String(event.context_json)).nodeId===node.id);expect(observations).toHaveLength(1);expect(JSON.parse(String(observations[0]!.context_json))).toMatchObject({nodeId:node.id,nodeRevision:node.node_revision,status:'cancelled',previousStatus:node.status});} + for(const node of before.nodes.filter(value=>value.kind!=='planning')){const status=node.kind==='condition'?'completed':'ready',observations=after.events.filter(event=>event.event_type==='execution.node.state'&&JSON.parse(String(event.context_json)).nodeId===node.id&&JSON.parse(String(event.context_json)).status===status);expect(observations).toHaveLength(1);const context=JSON.parse(String(observations[0]!.context_json)),current=after.nodes.find(value=>value.id===node.id)!;expect(context).toMatchObject({nodeId:node.id,status,previousStatus:'blocked'});expect(Number.isSafeInteger(context.nodeRevision)&&context.nodeRevision>=1&&context.nodeRevision<=Number(current.node_revision)).toBe(true);} const retained=await f.store.getCapacityWorkdayRun('team',started.workdayId);expect(appliedWorkdaySchema.parse(retained!.parameters.appliedPlan).endsAt).toBe(plan.endsAt);expect(after.assignments).toEqual(before.assignments);expect(after.reservations).toEqual(before.reservations);expect(after.usage).toEqual(before.usage);expect(after.ledger).toEqual(before.ledger); expect(await f.store.tickCapacityWorkdayRun('team',started.workdayId,plan.endsAt,'native-node-closeout')).toEqual(tick);expect(await f.snapshot()).toEqual(after); }finally{await f.close();} From 68f7676c690cf467372c6e67b52f1296ea7bdc16 Mon Sep 17 00:00:00 2001 From: Adrian Webb Date: Sat, 17 Oct 2026 04:36:30 -0400 Subject: [PATCH 20/24] test: bind immutable node births independently of later closeout revisions and states --- .../workdays/scheduling/architecture/node-birth-history.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/control-plane/capacity/workdays/scheduling/architecture/node-birth-history.ts b/tests/unit/control-plane/capacity/workdays/scheduling/architecture/node-birth-history.ts index 0632bcd0e..1f09b3586 100644 --- a/tests/unit/control-plane/capacity/workdays/scheduling/architecture/node-birth-history.ts +++ b/tests/unit/control-plane/capacity/workdays/scheduling/architecture/node-birth-history.ts @@ -3,11 +3,11 @@ import{canonicalStandardsJson}from'@treeseed/sdk/standards'; import{appliedWorkdaySchema,compileWorkday}from'@treeseed/sdk/agent-capacity'; import{expect}from'vitest'; -/** These controlled native fixtures create ready planning and blocked closeout nodes; direct SQL completion inputs do not manufacture history. */ +/** Birth is immutable revision one with ready planning or blocked closeout state. Later revisions/statuses are independently asserted by the owning transition cases; direct SQL inputs never rewrite original birth evidence. */ export function expectNodeBirthHistory(snapshot:{nodes:Record[];events:Record[]}){ const births=snapshot.events.filter(event=>event.event_type==='execution.node.state'&&JSON.parse(String(event.context_json)).previousStatus===null); expect(births).toHaveLength(snapshot.nodes.length);expect(new Set(births.map(event=>JSON.parse(String(event.context_json)).nodeId)).size).toBe(snapshot.nodes.length); - for(const node of snapshot.nodes){const expectedStatus=node.kind==='condition'||node.kind==='reporting'?'blocked':'ready';expect(node.status).toBe(expectedStatus);const events=births.filter(event=>JSON.parse(String(event.context_json)).nodeId===node.id);expect(events).toHaveLength(1);const event=events[0]!;expect(event).toMatchObject({team_id:node.team_id,project_id:node.project_id,run_id:node.workday_id,workday_id:node.workday_id,assignment_id:null,status:'recorded'});expect(JSON.parse(String(event.context_json))).toEqual({nodeId:node.id,nodeRevision:node.node_revision,graphRevision:node.graph_revision_created,status:expectedStatus,previousStatus:null});} + for(const node of snapshot.nodes){const expectedStatus=node.kind==='condition'||node.kind==='reporting'?'blocked':'ready';expect(['planning','condition','reporting']).toContain(node.kind);expect(Number.isSafeInteger(node.node_revision)&&Number(node.node_revision)>=1).toBe(true);const events=births.filter(event=>JSON.parse(String(event.context_json)).nodeId===node.id);expect(events).toHaveLength(1);const event=events[0]!;expect(event).toMatchObject({team_id:node.team_id,project_id:node.project_id,run_id:node.workday_id,workday_id:node.workday_id,assignment_id:null,status:'recorded'});expect(JSON.parse(String(event.context_json))).toEqual({nodeId:node.id,nodeRevision:1,graphRevision:node.graph_revision_created,status:expectedStatus,previousStatus:null});} } /** Independent native rows must retain the exact old/new canonical plan; no status or exit code substitutes for an observation. */ export function expectWorkdayLifecycleHistory(snapshot:{workdays:Record[];events:Record[]}){ From 89d6da82597d6e6e973f73d9ac9121d426339e05 Mon Sep 17 00:00:00 2001 From: Adrian Webb Date: Sat, 17 Oct 2026 05:13:01 -0400 Subject: [PATCH 21/24] test: retain complete handler inventory and governed Reporter in native preflight fixtures --- .../capacity/agents/handler-inspection.test.ts | 8 ++++---- .../architecture/proposal-decision-native.test.ts | 9 +++++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/tests/unit/control-plane/capacity/agents/handler-inspection.test.ts b/tests/unit/control-plane/capacity/agents/handler-inspection.test.ts index 1b12aff2c..34f6e53d9 100644 --- a/tests/unit/control-plane/capacity/agents/handler-inspection.test.ts +++ b/tests/unit/control-plane/capacity/agents/handler-inspection.test.ts @@ -91,7 +91,7 @@ describe('public configured handler inspection', () => { await expect(show.handler({ ...input, path: { ...input.path, agentSlug: 'retired-reader' } }, context)) .rejects.toMatchObject({ status: 404, code: 'project_agent_not_found' }); const expected = { projectId: 'project', handlers: [ - { id: 'writer', origin: 'agent-package' }, { id: 'configured/paused-reader', origin: 'project-runtime' }, + { id: 'writer', origin: 'agent-package' }, { id: 'reporter', origin: 'agent-package' }, { id: 'configured/paused-reader', origin: 'project-runtime' }, ] }; expect(await handlers.handler(input, context)).toEqual(expected); expect(await Promise.all([show.handler(input, context), show.handler(input, context)])).toEqual([result, result]); @@ -186,7 +186,7 @@ describe('public configured handler inspection', () => { const state = async () => ({ execution: await f.snapshot(), classes: await f.all('SELECT * FROM project_agent_classes ORDER BY id'), projects: await f.all('SELECT * FROM projects ORDER BY id') }); const before = await state(), input = { path: { projectId: 'project' }, query: {}, body: undefined }, frozen = structuredClone(input); - const expected = { projectId: 'project', handlers: [{ id: 'writer', origin: 'agent-package' }, { id: 'configured/reader', origin: 'project-runtime' }] }; + const expected = { projectId: 'project', handlers: [{ id: 'writer', origin: 'agent-package' }, { id: 'reporter', origin: 'agent-package' }, { id: 'configured/reader', origin: 'project-runtime' }] }; const list = registry.require('agents.handlers.list'), show = registry.require('agents.handlers.show'); expect(await list.handler(input, context)).toEqual(expected); for (const handler of expected.handlers) expect(await show.handler({ ...input, path: { projectId: 'project', handlerId: handler.id } }, context)) @@ -214,9 +214,9 @@ describe('public configured handler inspection', () => { } const before = { execution: await f.snapshot(), classes: await f.all('SELECT * FROM project_agent_classes ORDER BY id') }; const service = createAgentQueryService(f.store), expected = { projectId: 'project', handlers: [ - { id: 'writer', origin: 'agent-package' }, { id: 'configured/tail-reader', origin: 'project-runtime' }] }; + { id: 'writer', origin: 'agent-package' }, { id: 'reporter', origin: 'agent-package' }, { id: 'configured/tail-reader', origin: 'project-runtime' }] }; expect(await service.handlers(f.principal, 'project')).toEqual(expected); - expect(await service.handler(f.principal, 'project', 'configured/tail-reader')).toEqual({ projectId: 'project', handler: expected.handlers[1] }); + expect(await service.handler(f.principal, 'project', 'configured/tail-reader')).toEqual({ projectId: 'project', handler: expected.handlers[2] }); expect({ execution: await f.snapshot(), classes: await f.all('SELECT * FROM project_agent_classes ORDER BY id') }).toEqual(before); expect(f.calls).toEqual([]); } finally { await f.close(); } diff --git a/tests/unit/control-plane/governance/proposals/architecture/proposal-decision-native.test.ts b/tests/unit/control-plane/governance/proposals/architecture/proposal-decision-native.test.ts index 9be71d999..3c18bcbb3 100644 --- a/tests/unit/control-plane/governance/proposals/architecture/proposal-decision-native.test.ts +++ b/tests/unit/control-plane/governance/proposals/architecture/proposal-decision-native.test.ts @@ -60,6 +60,13 @@ describe('native proposal Decision authority', () => { } return definition; }); + // The public Workday boundary also requires one governed closeout profile. + // Publish it with these same exact library bytes before any governance work. + const closeout = profiles[0]; assert.ok(closeout); + closeout.activityProfiles.reporting = { handler: 'reporter', + prompt: { system: 'Commit the deterministic canonical Workday closeout.' }, + permissions: { content: { read: ['knowledge', 'proposal'], write: ['note'] }, tools: [] }, + dependsOn: { events: ['workday-closing'] } }; const profileInputs = profiles.map(definition => ({ definition, path: `agents/${definition.agentClass}.md`, raw: `---\n${stringify(definition)}---\n` })); const profileInputsBefore = structuredClone(profileInputs); @@ -391,6 +398,8 @@ describe('native proposal Decision authority', () => { const storedRows = await f.store.all('SELECT * FROM capacity_operation_receipts WHERE resource_type=? AND resource_id=?', ['workday_preflight', receipt.id]); expect(storedRows).toHaveLength(1); const persisted = object(JSON.parse(String(storedRows[0]!.response_json))); expect(persisted.receipt).toEqual(receipt); expect(persisted.intent).toEqual(intent); expect(object(object(persisted.runInput).parameters).decisionIds).toEqual([decisionId]); + expect(object(object(persisted.runInput).parameters).reportingAgentId).toBe(closeout.id); + expect(object(object(object(persisted.runInput).parameters).appliedPlan).reportingAgentId).toBe(closeout.id); const hash = (value: unknown) => `sha256:${createHash('sha256').update(canonicalJson(value)).digest('base64url')}`; expect(receipt.intentDigest).toBe(hash(intent)); expect(storedRows[0]!.request_digest).toBe(receipt.intentDigest); expect(receipt.demandSetDigest).toBe(hash({ selectedDemands: receipt.selectedDemands, objectives: [], proposalIds: [], decisionIds: [decisionId] })); const { preflightDigest, ...payload } = receipt; expect(preflightDigest).toBe(hash(payload)); From e53711768581605c941496e99cde328499481906 Mon Sep 17 00:00:00 2001 From: Adrian Webb Date: Sat, 17 Oct 2026 05:14:55 -0400 Subject: [PATCH 22/24] test: keep native governed profile construction in its existing proposal input fixture --- .../proposal-decision-native.test.ts | 21 ++------------- .../architecture/ready-proposal-fixture.ts | 26 +++++++++++++++++++ 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/tests/unit/control-plane/governance/proposals/architecture/proposal-decision-native.test.ts b/tests/unit/control-plane/governance/proposals/architecture/proposal-decision-native.test.ts index 3c18bcbb3..a5298bd5e 100644 --- a/tests/unit/control-plane/governance/proposals/architecture/proposal-decision-native.test.ts +++ b/tests/unit/control-plane/governance/proposals/architecture/proposal-decision-native.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from 'vitest'; import { validateDecisionAuthority, validateExecutionAuthorityReceipt } from '../../../../../../src/api/governance/decision-authority.ts'; -import { readyProposal } from './ready-proposal-fixture.ts'; +import { readyProposal, nativeProposalProfileInputs } from './ready-proposal-fixture.ts'; import { verifyNativeProposalReconciliation } from './proposal-reconciliation-fixture.ts'; import { createHash, generateKeyPairSync, randomUUID } from 'node:crypto'; import { stringify } from 'yaml'; @@ -51,24 +51,7 @@ describe('native proposal Decision authority', () => { } const originalInputs = structuredClone({ declaration, principal: f.principal, sources: f.sources }); const path = `proposals/${declaration.id}.mdx`, raw = `---\n${stringify(declaration)}---\n`; - const profiles = Object.values(f.profiles).filter(value => f.profiles[`${projectId}:${value.agentClass}`] === value) - .map(value => { - const definition = structuredClone(value); - if (canonicalSupply) { - definition.capabilities = ['treeseed.research.verification']; - for (const profile of Object.values(definition.activityProfiles)) if (profile) profile.permissions.content.read.push('decision'); - } - return definition; - }); - // The public Workday boundary also requires one governed closeout profile. - // Publish it with these same exact library bytes before any governance work. - const closeout = profiles[0]; assert.ok(closeout); - closeout.activityProfiles.reporting = { handler: 'reporter', - prompt: { system: 'Commit the deterministic canonical Workday closeout.' }, - permissions: { content: { read: ['knowledge', 'proposal'], write: ['note'] }, tools: [] }, - dependsOn: { events: ['workday-closing'] } }; - const profileInputs = profiles.map(definition => ({ definition, path: `agents/${definition.agentClass}.md`, - raw: `---\n${stringify(definition)}---\n` })); + const { profileInputs, closeout } = nativeProposalProfileInputs(f.profiles, projectId, canonicalSupply); const profileInputsBefore = structuredClone(profileInputs); const refsBefore = object(await f.client.repositories.refs(repository)); assert.ok(Array.isArray(refsBefore.refs)); diff --git a/tests/unit/control-plane/governance/proposals/architecture/ready-proposal-fixture.ts b/tests/unit/control-plane/governance/proposals/architecture/ready-proposal-fixture.ts index 2e5b81723..32f621dea 100644 --- a/tests/unit/control-plane/governance/proposals/architecture/ready-proposal-fixture.ts +++ b/tests/unit/control-plane/governance/proposals/architecture/ready-proposal-fixture.ts @@ -1,3 +1,6 @@ +import assert from 'node:assert/strict'; +import { stringify } from 'yaml'; +import type { AgentDefinition } from '@treeseed/sdk/agent-capacity'; /** Governed example data, not a copy of the canonical schema or a readiness implementation. */ export function readyWorkItem() { return { id: 'verify-boundary', activity: 'acting', agentClass: 'boundary-author', workspace: 'read-only', @@ -13,3 +16,26 @@ export function readyProposal() { request: 'Verify the exact governed boundary.', summary: 'One bounded, independently reviewed work item.', status: 'draft', executionPlan: { workItems: [readyWorkItem()] } }; } + +/** Exact controlled library inputs; the original native test publishes and reads these bytes. */ +export function nativeProposalProfileInputs(configured: Record, projectId: string, canonicalSupply: boolean) { + const profiles = Object.values(configured).filter(value => configured[`${projectId}:${value.agentClass}`] === value) + .map(value => { + const definition = structuredClone(value); + if (canonicalSupply) { + definition.capabilities = ['treeseed.research.verification']; + for (const profile of Object.values(definition.activityProfiles)) if (profile) profile.permissions.content.read.push('decision'); + } + return definition; + }); + // The public Workday boundary also requires one governed closeout profile. + // Publish it with these same exact library bytes before any governance work. + const closeout = profiles[0]; assert.ok(closeout); + closeout.activityProfiles.reporting = { handler: 'reporter', + prompt: { system: 'Commit the deterministic canonical Workday closeout.' }, + permissions: { content: { read: ['knowledge', 'proposal'], write: ['note'] }, tools: [] }, + dependsOn: { events: ['workday-closing'] } }; + const profileInputs = profiles.map(definition => ({ definition, path: `agents/${definition.agentClass}.md`, + raw: `---\n${stringify(definition)}---\n` })); + return { profileInputs, closeout }; +} From af4e020aaa67df59a90749f3b5c3cf11b85d4946 Mon Sep 17 00:00:00 2001 From: Adrian Webb Date: Sat, 17 Oct 2026 05:41:48 -0400 Subject: [PATCH 23/24] test: observe the owning preflight plan without inventing a stored request representation Retain the frozen persisted Reporter selector and all original native assertions. Read the actual public owning preflight projection for applied-plan authority. Run this same native case in the existing early focused boundary step; full fresh complete suites and every supplement remain unchanged before scenes. --- .github/workflows/verify.yml | 2 +- .../proposals/architecture/proposal-decision-native.test.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index 942f4b5e6..4b07478ec 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -95,7 +95,7 @@ jobs: - name: Build public API exports before native acceptance consumer regression run: npm run build:dist - name: Reproduce native lease transition history before complete verification - run: node node_modules/vitest/vitest.mjs run --config ./vitest.control-plane.config.ts tests/unit/control-plane/capacity/execution/admission/postgres.test.ts tests/unit/control-plane/release/provider-prerequisites.test.ts tests/unit/control-plane/providers/assignments/lifecycle/architecture/terminal-observation-postgres.test.ts tests/unit/control-plane/capacity/execution/graph/persistence/concurrent-results-postgres.test.ts tests/unit/control-plane/providers/assignments/architecture/recovery/operator-recovery-postgres.test.ts tests/unit/control-plane/providers/assignments/architecture/recovery/recovery-observation-postgres.test.ts tests/unit/control-plane/capacity/workdays/scheduling/architecture/workday-start-native.test.ts tests/unit/control-plane/capacity/workdays/lifecycle/concurrent-runs-postgres.test.ts tests/unit/control-plane/capacity/execution/graph/architecture/workday-closeout-persistence.test.ts tests/unit/control-plane/capacity/execution/architecture/initial/admission/session-authority-unit.test.ts tests/unit/control-plane/capacity/planning/assignment-estimate-integration.test.ts tests/unit/control-plane/capacity/planning/estimate-source-native.test.ts tests/unit/control-plane/providers/assignments/architecture/cancellation-persistence.test.ts tests/unit/control-plane/capacity/execution/architecture/initial/admission/resource-closure-unit.test.ts tests/unit/control-plane/capacity/execution/architecture/monitoring/node-status-history-postgres.test.ts tests/unit/control-plane/capacity/accounting/architecture/accounting-history-postgres.test.ts tests/unit/control-plane/capacity/execution/architecture/monitoring/node-review-exhaustion-postgres.test.ts tests/unit/control-plane/capacity/workdays/scheduling/architecture/workday-node-history-native.test.ts tests/unit/control-plane/capacity/execution/admission/discussion-binding.test.ts tests/unit/control-plane/capacity/execution/architecture/admission-replay-authority.test.ts tests/unit/control-plane/capacity/execution/architecture/admission-replay-native.test.ts tests/unit/control-plane/capacity/execution/admission/timeout-postgres.test.ts tests/unit/control-plane/capacity/execution/scheduling/planning/planning-window-evidence.test.ts tests/unit/control-plane/capacity/execution/scheduling/planning/planning-phase-native.test.ts tests/unit/control-plane/capacity/execution/admission/closeout/closeout-admission.test.ts tests/unit/control-plane/capacity/workdays/lifecycle/workday-lifecycle-observations.test.ts tests/unit/control-plane/capacity/execution/reporting/report-context-scope.test.ts tests/unit/control-plane/capacity/execution/reporting/report-context-lifecycle.test.ts tests/unit/control-plane/capacity/execution/architecture/monitoring/node-status-history.test.ts tests/unit/control-plane/capacity/execution/graph/architecture/workday-observation-persistence.test.ts tests/unit/control-plane/capacity/ontology/availability-history.test.ts tests/unit/control-plane/capacity/ontology/availability-postgres.test.ts + run: node node_modules/vitest/vitest.mjs run --config ./vitest.control-plane.config.ts tests/unit/control-plane/governance/proposals/architecture/proposal-decision-native.test.ts tests/unit/control-plane/capacity/execution/admission/postgres.test.ts tests/unit/control-plane/release/provider-prerequisites.test.ts tests/unit/control-plane/providers/assignments/lifecycle/architecture/terminal-observation-postgres.test.ts tests/unit/control-plane/capacity/execution/graph/persistence/concurrent-results-postgres.test.ts tests/unit/control-plane/providers/assignments/architecture/recovery/operator-recovery-postgres.test.ts tests/unit/control-plane/providers/assignments/architecture/recovery/recovery-observation-postgres.test.ts tests/unit/control-plane/capacity/workdays/scheduling/architecture/workday-start-native.test.ts tests/unit/control-plane/capacity/workdays/lifecycle/concurrent-runs-postgres.test.ts tests/unit/control-plane/capacity/execution/graph/architecture/workday-closeout-persistence.test.ts tests/unit/control-plane/capacity/execution/architecture/initial/admission/session-authority-unit.test.ts tests/unit/control-plane/capacity/planning/assignment-estimate-integration.test.ts tests/unit/control-plane/capacity/planning/estimate-source-native.test.ts tests/unit/control-plane/providers/assignments/architecture/cancellation-persistence.test.ts tests/unit/control-plane/capacity/execution/architecture/initial/admission/resource-closure-unit.test.ts tests/unit/control-plane/capacity/execution/architecture/monitoring/node-status-history-postgres.test.ts tests/unit/control-plane/capacity/accounting/architecture/accounting-history-postgres.test.ts tests/unit/control-plane/capacity/execution/architecture/monitoring/node-review-exhaustion-postgres.test.ts tests/unit/control-plane/capacity/workdays/scheduling/architecture/workday-node-history-native.test.ts tests/unit/control-plane/capacity/execution/admission/discussion-binding.test.ts tests/unit/control-plane/capacity/execution/architecture/admission-replay-authority.test.ts tests/unit/control-plane/capacity/execution/architecture/admission-replay-native.test.ts tests/unit/control-plane/capacity/execution/admission/timeout-postgres.test.ts tests/unit/control-plane/capacity/execution/scheduling/planning/planning-window-evidence.test.ts tests/unit/control-plane/capacity/execution/scheduling/planning/planning-phase-native.test.ts tests/unit/control-plane/capacity/execution/admission/closeout/closeout-admission.test.ts tests/unit/control-plane/capacity/workdays/lifecycle/workday-lifecycle-observations.test.ts tests/unit/control-plane/capacity/execution/reporting/report-context-scope.test.ts tests/unit/control-plane/capacity/execution/reporting/report-context-lifecycle.test.ts tests/unit/control-plane/capacity/execution/architecture/monitoring/node-status-history.test.ts tests/unit/control-plane/capacity/execution/graph/architecture/workday-observation-persistence.test.ts tests/unit/control-plane/capacity/ontology/availability-history.test.ts tests/unit/control-plane/capacity/ontology/availability-postgres.test.ts - run: npm run verify:direct - name: Verify real PostgreSQL backup-writer migration closure run: npx vitest run --config vitest.control-plane.config.ts tests/unit/control-plane/services/live/replication-migration-postgres.test.ts diff --git a/tests/unit/control-plane/governance/proposals/architecture/proposal-decision-native.test.ts b/tests/unit/control-plane/governance/proposals/architecture/proposal-decision-native.test.ts index a5298bd5e..fef8a14d5 100644 --- a/tests/unit/control-plane/governance/proposals/architecture/proposal-decision-native.test.ts +++ b/tests/unit/control-plane/governance/proposals/architecture/proposal-decision-native.test.ts @@ -382,7 +382,8 @@ describe('native proposal Decision authority', () => { expect(storedRows).toHaveLength(1); const persisted = object(JSON.parse(String(storedRows[0]!.response_json))); expect(persisted.receipt).toEqual(receipt); expect(persisted.intent).toEqual(intent); expect(object(object(persisted.runInput).parameters).decisionIds).toEqual([decisionId]); expect(object(object(persisted.runInput).parameters).reportingAgentId).toBe(closeout.id); - expect(object(object(object(persisted.runInput).parameters).appliedPlan).reportingAgentId).toBe(closeout.id); + const projected=await capacity.preflightCapacityWorkdayRunRequest('team',object(persisted.runInput)); + expect(object(projected.appliedPlan).reportingAgentId).toBe(closeout.id); const hash = (value: unknown) => `sha256:${createHash('sha256').update(canonicalJson(value)).digest('base64url')}`; expect(receipt.intentDigest).toBe(hash(intent)); expect(storedRows[0]!.request_digest).toBe(receipt.intentDigest); expect(receipt.demandSetDigest).toBe(hash({ selectedDemands: receipt.selectedDemands, objectives: [], proposalIds: [], decisionIds: [decisionId] })); const { preflightDigest, ...payload } = receipt; expect(preflightDigest).toBe(hash(payload)); From 8b013c29c19b7f57fb3e93ae9d425b6be5368c8e Mon Sep 17 00:00:00 2001 From: Adrian Webb Date: Sat, 17 Oct 2026 05:55:06 -0400 Subject: [PATCH 24/24] test: distinguish the read-only preflight projection from the existing reconciled graph variable --- .../proposals/architecture/proposal-decision-native.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/control-plane/governance/proposals/architecture/proposal-decision-native.test.ts b/tests/unit/control-plane/governance/proposals/architecture/proposal-decision-native.test.ts index fef8a14d5..bbc2a9030 100644 --- a/tests/unit/control-plane/governance/proposals/architecture/proposal-decision-native.test.ts +++ b/tests/unit/control-plane/governance/proposals/architecture/proposal-decision-native.test.ts @@ -382,8 +382,8 @@ describe('native proposal Decision authority', () => { expect(storedRows).toHaveLength(1); const persisted = object(JSON.parse(String(storedRows[0]!.response_json))); expect(persisted.receipt).toEqual(receipt); expect(persisted.intent).toEqual(intent); expect(object(object(persisted.runInput).parameters).decisionIds).toEqual([decisionId]); expect(object(object(persisted.runInput).parameters).reportingAgentId).toBe(closeout.id); - const projected=await capacity.preflightCapacityWorkdayRunRequest('team',object(persisted.runInput)); - expect(object(projected.appliedPlan).reportingAgentId).toBe(closeout.id); + const preflightProjection=await capacity.preflightCapacityWorkdayRunRequest('team',object(persisted.runInput)); + expect(object(preflightProjection.appliedPlan).reportingAgentId).toBe(closeout.id); const hash = (value: unknown) => `sha256:${createHash('sha256').update(canonicalJson(value)).digest('base64url')}`; expect(receipt.intentDigest).toBe(hash(intent)); expect(storedRows[0]!.request_digest).toBe(receipt.intentDigest); expect(receipt.demandSetDigest).toBe(hash({ selectedDemands: receipt.selectedDemands, objectives: [], proposalIds: [], decisionIds: [decisionId] })); const { preflightDigest, ...payload } = receipt; expect(preflightDigest).toBe(hash(payload));