diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index eb374b0f..6e86060a 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -26,8 +26,22 @@ jobs: - name: Install dependencies timeout-minutes: 20 + env: + TREESEED_SKIP_PACKAGE_PREPARE: "1" run: npm run release:setup + - name: Download exact integrated UI package + uses: actions/download-artifact@v4 + with: + repository: treeseed-ai/ui + run-id: 36729378278 + name: ui-b0c9a2bdf1eed181950c1202a24ab3d9af012833 + github-token: ${{ github.token }} + path: .treeseed/ci-ui + + - name: Install exact integrated UI package + run: npm install --ignore-scripts --no-save --package-lock=false .treeseed/ci-ui/*.tgz + - name: Verify package run: npm run verify:direct diff --git a/src/lib/market/api-client/capacity/allocations/queries/list-capacity-allocation-sets.ts b/src/lib/market/api-client/capacity/allocations/queries/list-capacity-allocation-sets.ts deleted file mode 100644 index efeea8ca..00000000 --- a/src/lib/market/api-client/capacity/allocations/queries/list-capacity-allocation-sets.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { APIContext } from 'astro'; -import { REMOTE_CONTRACT_HEADER, REMOTE_CONTRACT_VERSION } from '@treeseed/sdk/site-contracts/catalog'; -import type { AccountDeletionBlocker, AccountEmailAddress, AccountEmailMutationResult, AccountIdentity, AccountMutationResult, AccountNotification, AccountWebSession, AuthProviderCapability, NotificationPreferences, NotificationProject, PersonalTheme, PersonalThemeDraft, UsernameClaimResult, WebAuthenticationResult } from '@treeseed/sdk/account-contracts'; -import type { AstroLike, ApiClientFacade } from '../../../../api-client.ts'; -import { getNodeCrypto, randomId, runtimeEnv, envValue, resolveApiBaseUrl, isObject, unwrapEnvelope, createApiFacade, safeTokenEquals } from '../../../../api-client.ts'; -export function listCapacityAllocationSetsMethod(this: ApiClientFacade, teamId: string) { - return this.request('GET', `/v1/teams/${encodeURIComponent(teamId)}/capacity/allocation-sets`); -} diff --git a/src/lib/market/api-client/capacity/planning/queries/get-capacity-plan.ts b/src/lib/market/api-client/capacity/planning/queries/get-capacity-plan.ts deleted file mode 100644 index f84dc2ae..00000000 --- a/src/lib/market/api-client/capacity/planning/queries/get-capacity-plan.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { APIContext } from 'astro'; -import { REMOTE_CONTRACT_HEADER, REMOTE_CONTRACT_VERSION } from '@treeseed/sdk/site-contracts/catalog'; -import type { AccountDeletionBlocker, AccountEmailAddress, AccountEmailMutationResult, AccountIdentity, AccountMutationResult, AccountNotification, AccountWebSession, AuthProviderCapability, NotificationPreferences, NotificationProject, PersonalTheme, PersonalThemeDraft, UsernameClaimResult, WebAuthenticationResult } from '@treeseed/sdk/account-contracts'; -import type { AstroLike, ApiClientFacade } from '../../../../api-client.ts'; -import { getNodeCrypto, randomId, runtimeEnv, envValue, resolveApiBaseUrl, isObject, unwrapEnvelope, createApiFacade, safeTokenEquals } from '../../../../api-client.ts'; -export function getCapacityPlanMethod(this: ApiClientFacade, capacityPlanId: string) { - return this.request('GET', `/v1/capacity-plans/${encodeURIComponent(capacityPlanId)}`); -} diff --git a/src/lib/market/api-client/capacity/planning/queries/list-capacity-routing-decisions-for-project.ts b/src/lib/market/api-client/capacity/planning/queries/list-capacity-routing-decisions-for-project.ts deleted file mode 100644 index 9bb4f3ae..00000000 --- a/src/lib/market/api-client/capacity/planning/queries/list-capacity-routing-decisions-for-project.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { APIContext } from 'astro'; -import { REMOTE_CONTRACT_HEADER, REMOTE_CONTRACT_VERSION } from '@treeseed/sdk/site-contracts/catalog'; -import type { AccountDeletionBlocker, AccountEmailAddress, AccountEmailMutationResult, AccountIdentity, AccountMutationResult, AccountNotification, AccountWebSession, AuthProviderCapability, NotificationPreferences, NotificationProject, PersonalTheme, PersonalThemeDraft, UsernameClaimResult, WebAuthenticationResult } from '@treeseed/sdk/account-contracts'; -import type { AstroLike, ApiClientFacade } from '../../../../api-client.ts'; -import { getNodeCrypto, randomId, runtimeEnv, envValue, resolveApiBaseUrl, isObject, unwrapEnvelope, createApiFacade, safeTokenEquals } from '../../../../api-client.ts'; -export function listCapacityRoutingDecisionsForProjectMethod(this: ApiClientFacade, projectId: string, limit = 100) { - return this.request('GET', `/v1/projects/${encodeURIComponent(projectId)}/capacity/routing-decisions?limit=${encodeURIComponent(String(limit))}`); -} diff --git a/src/lib/market/api-client/capacity/planning/queries/list-decision-capacity-plans.ts b/src/lib/market/api-client/capacity/planning/queries/list-decision-capacity-plans.ts deleted file mode 100644 index 2b3264ab..00000000 --- a/src/lib/market/api-client/capacity/planning/queries/list-decision-capacity-plans.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { APIContext } from 'astro'; -import { REMOTE_CONTRACT_HEADER, REMOTE_CONTRACT_VERSION } from '@treeseed/sdk/site-contracts/catalog'; -import type { AccountDeletionBlocker, AccountEmailAddress, AccountEmailMutationResult, AccountIdentity, AccountMutationResult, AccountNotification, AccountWebSession, AuthProviderCapability, NotificationPreferences, NotificationProject, PersonalTheme, PersonalThemeDraft, UsernameClaimResult, WebAuthenticationResult } from '@treeseed/sdk/account-contracts'; -import type { AstroLike, ApiClientFacade } from '../../../../api-client.ts'; -import { getNodeCrypto, randomId, runtimeEnv, envValue, resolveApiBaseUrl, isObject, unwrapEnvelope, createApiFacade, safeTokenEquals } from '../../../../api-client.ts'; -export function listDecisionCapacityPlansMethod(this: ApiClientFacade, decisionId: string, filters: { - status?: string | null; -} = {}) { - const query = new URLSearchParams(); - if (filters.status) - query.set('status', filters.status); - return this.request('GET', `/v1/decisions/${encodeURIComponent(decisionId)}/capacity-plans${query.toString() ? `?${query}` : ''}`); -} diff --git a/src/lib/market/api-client/interface.ts b/src/lib/market/api-client/interface.ts index dbef735d..b8319aec 100644 --- a/src/lib/market/api-client/interface.ts +++ b/src/lib/market/api-client/interface.ts @@ -44,7 +44,6 @@ declare module "../api-client.ts" { evaluateTeamDeletionBlockers: typeof import("./teams/contracts/evaluate-team-deletion-blockers.ts").evaluateTeamDeletionBlockersMethod; fulfillCommerceOrderItemArtifact: typeof import("./commerce/orders/lifecycle/fulfill-commerce-order-item-artifact.ts").fulfillCommerceOrderItemArtifactMethod; fulfillCommerceServiceContract: typeof import("./commerce/services/lifecycle/fulfill-commerce-service-contract.ts").fulfillCommerceServiceContractMethod; - getCapacityPlan: typeof import("./capacity/planning/queries/get-capacity-plan.ts").getCapacityPlanMethod; getCatalogItemBySlug: typeof import("./commerce/catalog/queries/get-catalog-item-by-slug.ts").getCatalogItemBySlugMethod; getCommerceCapacityListingForProduct: typeof import("./commerce/capacity/queries/get-commerce-capacity-listing-for-product.ts").getCommerceCapacityListingForProductMethod; getCommerceCapacityListingInquiry: typeof import("./commerce/capacity/queries/get-commerce-capacity-listing-inquiry.ts").getCommerceCapacityListingInquiryMethod; @@ -61,7 +60,6 @@ declare module "../api-client.ts" { getCommonsParticipantMe: typeof import("./governance/commons/queries/get-commons-participant-me.ts").getCommonsParticipantMeMethod; getCommonsProposal: typeof import("./governance/commons/queries/get-commons-proposal.ts").getCommonsProposalMethod; getCommonsSummary: typeof import("./governance/commons/queries/get-commons-summary.ts").getCommonsSummaryMethod; - getDecisionPlanningStatus: typeof import("./support/queries/get-decision-planning-status.ts").getDecisionPlanningStatusMethod; getProjectAgentsSummary: typeof import("./projects/projects-core/queries/get-project-agents-summary.ts").getProjectAgentsSummaryMethod; getProjectByTeamAndSlug: typeof import("./projects/projects-core/queries/get-project-by-team-and-slug.ts").getProjectByTeamAndSlugMethod; getProjectCapacityRuntimeDiagnostics: typeof import("./capacity/observability/queries/get-project-capacity-runtime-diagnostics.ts").getProjectCapacityRuntimeDiagnosticsMethod; @@ -82,9 +80,7 @@ declare module "../api-client.ts" { listApprovalRequestsForProject: typeof import("./projects/projects-core/queries/list-approval-requests-for-project.ts").listApprovalRequestsForProjectMethod; listApprovalRequestsForTeam: typeof import("./teams/queries/list-approval-requests-for-team.ts").listApprovalRequestsForTeamMethod; listAuditEventsForTarget: typeof import("./support/queries/list-audit-events-for-target.ts").listAuditEventsForTargetMethod; - listCapacityAllocationSets: typeof import("./capacity/allocations/queries/list-capacity-allocation-sets.ts").listCapacityAllocationSetsMethod; listCapacityLedgerEntries: typeof import("./capacity/accounting/queries/list-capacity-ledger-entries.ts").listCapacityLedgerEntriesMethod; - listCapacityRoutingDecisionsForProject: typeof import("./capacity/planning/queries/list-capacity-routing-decisions-for-project.ts").listCapacityRoutingDecisionsForProjectMethod; listCatalogArtifactVersions: typeof import("./commerce/orders/queries/list-catalog-artifact-versions.ts").listCatalogArtifactVersionsMethod; listCatalogItems: typeof import("./commerce/catalog/queries/list-catalog-items.ts").listCatalogItemsMethod; listCommerceCapacityListingInquiries: typeof import("./commerce/capacity/queries/list-commerce-capacity-listing-inquiries.ts").listCommerceCapacityListingInquiriesMethod; @@ -105,8 +101,6 @@ declare module "../api-client.ts" { listCommonsParticipants: typeof import("./governance/commons/queries/list-commons-participants.ts").listCommonsParticipantsMethod; listCommonsProposals: typeof import("./governance/commons/queries/list-commons-proposals.ts").listCommonsProposalsMethod; listCommonsQuestions: typeof import("./governance/commons/queries/list-commons-questions.ts").listCommonsQuestionsMethod; - listDecisionCapacityPlans: typeof import("./capacity/planning/queries/list-decision-capacity-plans.ts").listDecisionCapacityPlansMethod; - listDecisionExecutionInputs: typeof import("./support/queries/list-decision-execution-inputs.ts").listDecisionExecutionInputsMethod; listExecutionRuns: typeof import("./support/queries/list-execution-runs.ts").listExecutionRunsMethod; listPersistedTeamInboxItems: typeof import("./teams/queries/list-persisted-team-inbox-items.ts").listPersistedTeamInboxItemsMethod; listProjectAgentClasses: typeof import("./projects/agents/queries/list-project-agent-classes.ts").listProjectAgentClassesMethod; diff --git a/src/lib/market/api-client/methods.ts b/src/lib/market/api-client/methods.ts index 8242181b..d5b7b6f1 100644 --- a/src/lib/market/api-client/methods.ts +++ b/src/lib/market/api-client/methods.ts @@ -135,7 +135,6 @@ import { getProjectTreeDxLibraryMethod } from "./projects/knowledge/queries/get- import { upsertProjectTreeDxLibraryMethod } from "./projects/knowledge/creation/upsert-project-tree-dx-library.ts"; import { getProjectRepositoryTopologyMethod } from "./projects/repositories/queries/get-project-repository-topology.ts"; import { updateProjectRepositoryTopologyMethod } from "./projects/repositories/updates/update-project-repository-topology.ts"; -import { listCapacityAllocationSetsMethod } from "./capacity/allocations/queries/list-capacity-allocation-sets.ts"; import { listProviderAvailabilitySessionsMethod } from "./capacity/providers/queries/list-provider-availability-sessions.ts"; import { listProviderAssignmentsMethod } from "./capacity/assignments/queries/list-provider-assignments.ts"; import { listExecutionRunsMethod } from "./support/queries/list-execution-runs.ts"; @@ -145,16 +144,11 @@ import { listProjectAgentFallbackOutputsMethod } from "./projects/agents/queries import { listProjectTreeDxProxyAuditMethod } from "./projects/knowledge/queries/list-project-tree-dx-proxy-audit.ts"; import { getProjectCapacityRuntimeDiagnosticsMethod } from "./capacity/observability/queries/get-project-capacity-runtime-diagnostics.ts"; import { getProviderAssignmentExplanationMethod } from "./capacity/assignments/queries/get-provider-assignment-explanation.ts"; -import { getDecisionPlanningStatusMethod } from "./support/queries/get-decision-planning-status.ts"; -import { listDecisionExecutionInputsMethod } from "./support/queries/list-decision-execution-inputs.ts"; -import { listDecisionCapacityPlansMethod } from "./capacity/planning/queries/list-decision-capacity-plans.ts"; -import { getCapacityPlanMethod } from "./capacity/planning/queries/get-capacity-plan.ts"; import { getWorkdayCapacitySummaryMethod } from "./capacity/workdays/queries/get-workday-capacity-summary.ts"; import { listWorkdayRunsMethod } from "./capacity/workdays/queries/list-workday-runs.ts"; import { createWorkdayRunMethod } from "./capacity/workdays/creation/create-workday-run.ts"; import { getWorkdayRunMethod } from "./capacity/workdays/queries/get-workday-run.ts"; import { listCapacityLedgerEntriesMethod } from "./capacity/accounting/queries/list-capacity-ledger-entries.ts"; -import { listCapacityRoutingDecisionsForProjectMethod } from "./capacity/planning/queries/list-capacity-routing-decisions-for-project.ts"; import { listSeedRunsMethod } from "./seeds/queries/list-seed-runs.ts"; import { listCatalogItemsMethod } from "./commerce/catalog/queries/list-catalog-items.ts"; import { getCatalogItemBySlugMethod } from "./commerce/catalog/queries/get-catalog-item-by-slug.ts"; @@ -336,7 +330,6 @@ export function installApiClientFacadeMethods(prototype: ApiClientFacade) { prototype.getProjectRepositoryTopology = getProjectRepositoryTopologyMethod; prototype.updateProjectRepositoryTopology = updateProjectRepositoryTopologyMethod; - prototype.listCapacityAllocationSets = listCapacityAllocationSetsMethod; prototype.listProviderAvailabilitySessions = listProviderAvailabilitySessionsMethod; prototype.listProviderAssignments = listProviderAssignmentsMethod; @@ -350,17 +343,11 @@ export function installApiClientFacadeMethods(prototype: ApiClientFacade) { getProjectCapacityRuntimeDiagnosticsMethod; prototype.getProviderAssignmentExplanation = getProviderAssignmentExplanationMethod; - prototype.getDecisionPlanningStatus = getDecisionPlanningStatusMethod; - prototype.listDecisionExecutionInputs = listDecisionExecutionInputsMethod; - prototype.listDecisionCapacityPlans = listDecisionCapacityPlansMethod; - prototype.getCapacityPlan = getCapacityPlanMethod; prototype.getWorkdayCapacitySummary = getWorkdayCapacitySummaryMethod; prototype.listWorkdayRuns = listWorkdayRunsMethod; prototype.createWorkdayRun = createWorkdayRunMethod; prototype.getWorkdayRun = getWorkdayRunMethod; prototype.listCapacityLedgerEntries = listCapacityLedgerEntriesMethod; - prototype.listCapacityRoutingDecisionsForProject = - listCapacityRoutingDecisionsForProjectMethod; prototype.listSeedRuns = listSeedRunsMethod; prototype.listCatalogItems = listCatalogItemsMethod; prototype.getCatalogItemBySlug = getCatalogItemBySlugMethod; diff --git a/src/lib/market/api-client/support/queries/get-decision-planning-status.ts b/src/lib/market/api-client/support/queries/get-decision-planning-status.ts deleted file mode 100644 index 24ba9382..00000000 --- a/src/lib/market/api-client/support/queries/get-decision-planning-status.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { APIContext } from 'astro'; -import { REMOTE_CONTRACT_HEADER, REMOTE_CONTRACT_VERSION } from '@treeseed/sdk/site-contracts/catalog'; -import type { AccountDeletionBlocker, AccountEmailAddress, AccountEmailMutationResult, AccountIdentity, AccountMutationResult, AccountNotification, AccountWebSession, AuthProviderCapability, NotificationPreferences, NotificationProject, PersonalTheme, PersonalThemeDraft, UsernameClaimResult, WebAuthenticationResult } from '@treeseed/sdk/account-contracts'; -import type { AstroLike, ApiClientFacade } from '../../../api-client.ts'; -import { getNodeCrypto, randomId, runtimeEnv, envValue, resolveApiBaseUrl, isObject, unwrapEnvelope, createApiFacade, safeTokenEquals } from '../../../api-client.ts'; -export function getDecisionPlanningStatusMethod(this: ApiClientFacade, decisionId: string) { - return this.request('GET', `/v1/decisions/${encodeURIComponent(decisionId)}/planning-status`); -} diff --git a/src/lib/market/api-client/support/queries/list-decision-execution-inputs.ts b/src/lib/market/api-client/support/queries/list-decision-execution-inputs.ts deleted file mode 100644 index 338556d2..00000000 --- a/src/lib/market/api-client/support/queries/list-decision-execution-inputs.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { APIContext } from 'astro'; -import { REMOTE_CONTRACT_HEADER, REMOTE_CONTRACT_VERSION } from '@treeseed/sdk/site-contracts/catalog'; -import type { AccountDeletionBlocker, AccountEmailAddress, AccountEmailMutationResult, AccountIdentity, AccountMutationResult, AccountNotification, AccountWebSession, AuthProviderCapability, NotificationPreferences, NotificationProject, PersonalTheme, PersonalThemeDraft, UsernameClaimResult, WebAuthenticationResult } from '@treeseed/sdk/account-contracts'; -import type { AstroLike, ApiClientFacade } from '../../../api-client.ts'; -import { getNodeCrypto, randomId, runtimeEnv, envValue, resolveApiBaseUrl, isObject, unwrapEnvelope, createApiFacade, safeTokenEquals } from '../../../api-client.ts'; -export function listDecisionExecutionInputsMethod(this: ApiClientFacade, decisionId: string) { - return this.request('GET', `/v1/decisions/${encodeURIComponent(decisionId)}/execution-inputs`); -} diff --git a/src/view-models/agent-lab/agent-lab-frame.ts b/src/view-models/agent-lab/agent-lab-frame.ts index b68204fa..4dc96ad8 100644 --- a/src/view-models/agent-lab/agent-lab-frame.ts +++ b/src/view-models/agent-lab/agent-lab-frame.ts @@ -47,7 +47,7 @@ export async function loadAgentLabFrame(api: ApiClientFacade, team: { id: string }); const activity = { revision: 'catalog-foundation', generatedAt: new Date().toISOString(), cursor: null, upserts: [], removedIds: [] }; const series = { revision: 'catalog-foundation', generatedAt: new Date().toISOString(), cursor: null, upserts: [], removedIds: [] }; - const allocation = { revision: 'catalog-foundation', generatedAt: new Date().toISOString(), canManage: false, activeAllocationSetId: null, + const allocation = { revision: 'catalog-foundation', generatedAt: new Date().toISOString(), time: { availableSeconds: null, requestedSeconds: 0, reservedSeconds: 0, activeSeconds: 0, elapsedSeconds: 0, releasedSeconds: 0, remainingSeconds: null, overrunSeconds: 0 }, projects: [], agentClasses: [], workdayTime: [] }; const atlas = fallbackAtlas(team.id, overview); return { @@ -56,7 +56,7 @@ export async function loadAgentLabFrame(api: ApiClientFacade, team: { id: string activity: activity as AgentLabDelta, series: series as AgentLabDelta, allocation: allocation as AllocationSnapshot, - endpoints: { overview: '', activity: '', metricSeries: '', allocation: '', viewState: '' }, + endpoints: { overview: '', activity: '', metricSeries: '', viewState: '' }, atlasEndpoints:{projection:'',delta:'',stream:'',detail:'',assignmentGraphs:'',viewState:'',createAgent:`/app/work/build?create=agent`,createGroup:`/app/work/build?create=group`,createProject:'/app/projects',connectService:'/app/services/new',configureCapacity:'/app/capacity'}, targetEndpoint: '', preference: { enabled: preferences.realTimeUpdates, intervalSeconds: preferences.realTimePollingIntervalSeconds }, diff --git a/src/view-models/command/situations.ts b/src/view-models/command/situations.ts index d3abfb65..849a06fc 100644 --- a/src/view-models/command/situations.ts +++ b/src/view-models/command/situations.ts @@ -81,14 +81,6 @@ export function deriveCommandSituations(snapshot: CommandSnapshot, now = Date.no timestamp: dateValue(item.updatedAt, item.createdAt), href: text(item.href, '/app/projects'), actionLabel: 'Inspect evidence', evidence: 'Persisted operational inbox evidence', inferred: false, priority: 94 })); } - for (const decision of snapshot.decisions) { - const accepted = ['accepted', 'approved', 'decided'].includes(String(decision.status ?? decision.outcome ?? '')); - if (!accepted || decision.capacityPlanId || decision.capacity_plan_id) continue; - values.push(situation({ id: `decision:${decision.id}`, title: 'Decision ready but not capacity-planned', - description: text(decision.title, decision.summary, 'An authorized decision has no linked capacity plan.'), status: 'planning required', tone: 'warning', - timestamp: dateValue(decision.decidedAt, decision.updatedAt, decision.createdAt), href: '/app/focus/decisions', actionLabel: 'Enter focused review', - evidence: 'Decision planning provenance', inferred: true, priority: 80 })); - } for (const project of snapshot.projects) { const state = `${project.status ?? ''} ${project.releaseStatus ?? ''} ${project.forecastStatus ?? ''}`.toLowerCase(); if (!['at_risk', 'blocked', 'delayed', 'failed'].some((value) => state.includes(value))) continue; diff --git a/tests/unit/brand-assets.test.ts b/tests/unit/brand-assets.test.ts index cfc61ad1..377444b1 100644 --- a/tests/unit/brand-assets.test.ts +++ b/tests/unit/brand-assets.test.ts @@ -3,12 +3,15 @@ import { execFileSync } from 'node:child_process'; import { mkdtempSync, readFileSync, rmSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join, resolve } from 'node:path'; +import { createRequire } from 'node:module'; + +const require = createRequire(import.meta.url); it('materializes the canonical TreeSeed logo at both advertised public asset URLs', () => { const root = mkdtempSync(join(tmpdir(), 'treeseed-brand-')); try { - execFileSync(process.execPath, ['--experimental-strip-types', resolve('scripts/brand/sync-assets.ts')], { cwd: root }); - const canonical = readFileSync(new URL(import.meta.resolve('@treeseed/ui/assets/treeseed-logo.svg'))); + execFileSync(process.execPath, ['--import', require.resolve('tsx'), resolve('scripts/brand/sync-assets.ts')], { cwd: root }); + const canonical = readFileSync(require.resolve('@treeseed/ui/assets/treeseed-logo.svg')); expect(readFileSync(join(root, 'public/logo.svg'))).toEqual(canonical); expect(readFileSync(join(root, 'public/favicon.svg'))).toEqual(canonical); } finally { rmSync(root, { recursive: true, force: true }); } diff --git a/tests/unit/command/situations.test.ts b/tests/unit/command/situations.test.ts index e4900744..bdd6473a 100644 --- a/tests/unit/command/situations.test.ts +++ b/tests/unit/command/situations.test.ts @@ -17,7 +17,8 @@ describe('command situations', () => { snapshot.decisions = [{ id: 'd', status: 'accepted', title: 'Ship it' }]; snapshot.projects = [{ id: 'p1', name: 'Market', forecastStatus: 'at_risk' }]; const derived = deriveCommandSituations(snapshot, Date.parse('2026-08-03T16:00:00.000Z')); - for (const id of ['workday:w', 'execution:e', 'lease:x', 'providers:none', 'approval:a', 'budget:r', 'guarantee:g', 'decision:d', 'project:p1']) expect(derived.map((item) => item.id), id).toContain(id); + for (const id of ['workday:w', 'execution:e', 'lease:x', 'providers:none', 'approval:a', 'budget:r', 'guarantee:g', 'project:p1']) expect(derived.map((item) => item.id), id).toContain(id); + expect(derived.some((item) => item.id === 'decision:d')).toBe(false); expect(derived[0].priority).toBeGreaterThanOrEqual(derived.at(-1)!.priority); expect(derived.find((item) => item.id === 'lease:x')?.inferred).toBe(true); });