Files
zopu-code/packages/primitives/src/work-resolution.test.ts
-Puter a8d946b6a9 Slice 4 control-plane repairs, lint/catalog cleanup, Flue adapter fixes
Convex control plane (Slices 1-4 prerequisites for Slice 5):
- Versioned Definition/Design persistence: revisions preserve history
  instead of deleting prior slices/approvals
- Fenced conversation turn queue: attempt-numbered leases prevent stale
  worker overwrites; expired turns reconciled by cron
- Fenced Run/Attempt claiming: only queued attempts from running Runs can
  be claimed; lease expiry checks on every finish/checkpoint
- Multi-slice progression: successful slice marks next slice ready instead
  of completing the whole Work; completed Runs blocked from retry
- Typed AttemptClassification in schema and resolver decisions table
- Durable resolver decisions for normal outcomes, cancellation, and
  lease-expiry recovery
- Persistent artifacts and delivery metadata with provenance, source
  revision, verification status, and controlled delivery transitions
- High-impact open questions block definition approval
- Question submission gated to defining/awaiting-approval states only
- Delivery status updates validate JSON metadata before persisting
- Planner failures recorded as durable blocked events
- Approval identity uses canonical tokenIdentifier

Primitives:
- decodeDefinition separates decode from validate
- Design validation enforces 1-4 slices with unique IDs and valid deps
- Artifact and delivery draft schemas with verified-revision binding
- Delivery status transition table

Package management:
- Consolidated shared deps into single catalog (hono, valibot, streamdown,
  @types/react, @types/node, @tailwindcss/*, react-native)
- Removed cross-version Hono boundary: flue() exported as Fetchable
- Deleted bun.lock and regenerated from clean catalog resolution

Lint/format:
- Removed .eslintignore; oxc uses native ignorePatterns in oxlint.config.ts
- Deleted redundant packages/backend/.oxlintrc.json
- Added repos/** and scripts/** to ignore patterns
- Convex-specific rule overrides for ES2022 target constraints
- Fixed all oxc errors in fluePersistence.ts and agents/src/db.ts
- Fixed all formatting across changed files
2026-07-28 02:53:05 +05:30

175 lines
5.4 KiB
TypeScript

import { Effect } from "effect";
import { describe, expect, test } from "vitest";
import { FakeHarnessLive } from "./harness-runtime";
import { defaultCodingKitV0, resolveOutcome, shouldRetry } from "./resolver";
import { decodeDefinition, validateDefinition } from "./work-definition";
import { validateDesignPacket } from "./work-design";
import { canTransitionWork } from "./work-lifecycle";
const definition = {
acceptanceCriteria: ["terminal outcome"],
affectedUsers: ["founders"],
assumptions: [],
constraints: [],
desiredOutcome: "A visible terminal simulation exists",
inScope: ["fake execution"],
outOfScope: ["real sandboxing"],
problem: "A deterministic build path is needed",
questions: [
{
alternatives: [],
id: "q1",
impact: "high",
prompt: "Which runtime?",
status: "open",
},
],
requiredArtifacts: ["events"],
risk: "medium",
version: 1,
};
const probeOutcome = (
classification: Parameters<typeof resolveOutcome>[0]["classification"],
retryable = false
) => ({ classification, retryable, summary: "probe" });
describe("work resolution contracts", () => {
test("high-impact open questions block definition approval", async () => {
await expect(
Effect.runPromise(decodeDefinition(definition))
).resolves.toEqual(definition);
await expect(
Effect.runPromise(validateDefinition(definition))
).rejects.toThrow(/High-impact/u);
});
test("question identities are unique within a Definition version", async () => {
await expect(
Effect.runPromise(
decodeDefinition({
...definition,
questions: [definition.questions[0], definition.questions[0]],
})
)
).rejects.toThrow(/Question ID must be unique/u);
});
test("observable slices and terminal fake outcomes are enforced", async () => {
const approved = await Effect.runPromise(
validateDefinition({ ...definition, questions: [] })
);
const design = await Effect.runPromise(
validateDesignPacket({
architectureSummary: "small",
callFlowDelta: [],
concerns: [],
definitionVersion: approved.version,
evidenceRequirements: ["event"],
fileTreeDelta: [],
impactMap: { files: [], modules: [], risks: [], summary: "small" },
invariants: ["terminal"],
keyInterfaces: [],
slices: [
{
codeBoundaries: ["runtime"],
dependsOn: [],
evidenceRequirements: ["event"],
id: "s1",
objective: "one",
observableBehavior: "visible",
reviewRequired: false,
title: "one",
verification: ["assert"],
},
],
tradeoffs: [],
version: 1,
})
);
expect(design.slices).toHaveLength(1);
const [, outcome] = await Effect.runPromise(
FakeHarnessLive(() => 1).run({ scenario: "success" })
);
expect(outcome.classification).toBe("Succeeded");
expect(outcome.summary).toMatch(/no implementation/u);
const [, firstTransient] = await Effect.runPromise(
FakeHarnessLive(() => 1).run({
attemptNumber: 1,
scenario: "transient-failure-then-success",
})
);
const [, recoveredTransient] = await Effect.runPromise(
FakeHarnessLive(() => 1).run({
attemptNumber: 2,
scenario: "transient-failure-then-success",
})
);
expect(firstTransient.classification).toBe("RetryableFailure");
expect(recoveredTransient.classification).toBe("Succeeded");
expect(
shouldRetry(
{
classification: "RetryableFailure",
retryable: true,
summary: "retry",
},
1,
defaultCodingKitV0.retryPolicy
)
).toBe(true);
expect(canTransitionWork("ready", "executing")).toBe(true);
});
});
describe("resolver decisions", () => {
const policy = defaultCodingKitV0.retryPolicy;
test("retries a retryable failure while the budget remains", () => {
expect(
resolveOutcome(probeOutcome("RetryableFailure", true), 1, policy)
).toEqual({ kind: "retry" });
});
test("settles RetryableFailure as failed once the budget is exhausted", () => {
expect(
resolveOutcome(probeOutcome("RetryableFailure", true), 3, policy)
).toEqual({
kind: "terminal",
workStatus: "failed",
});
});
test("maps each terminal classification to its Work status", () => {
expect(resolveOutcome(probeOutcome("Succeeded"), 1, policy)).toEqual({
kind: "terminal",
workStatus: "completed",
});
expect(resolveOutcome(probeOutcome("PermanentFailure"), 1, policy)).toEqual(
{
kind: "terminal",
workStatus: "failed",
}
);
expect(resolveOutcome(probeOutcome("NeedsInput"), 1, policy)).toEqual({
kind: "terminal",
workStatus: "needs-input",
});
expect(resolveOutcome(probeOutcome("Blocked"), 1, policy)).toEqual({
kind: "terminal",
workStatus: "blocked",
});
expect(resolveOutcome(probeOutcome("Cancelled"), 1, policy)).toEqual({
kind: "terminal",
workStatus: "ready",
});
});
test("completed and cancelled are not silently reopened", () => {
expect(canTransitionWork("completed", "defining")).toBe(false);
expect(canTransitionWork("cancelled", "proposed")).toBe(false);
expect(canTransitionWork("ready", "executing")).toBe(true);
});
});