feat: consolidate agent execution stack
This commit is contained in:
@@ -6,7 +6,7 @@ import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
getExecutableGitSoftware,
|
||||
makeGitExecutablesRunnable,
|
||||
} from "./agent-os-git-software";
|
||||
} from "./agent-os-git-software.ts";
|
||||
|
||||
const TAR_BLOCK_SIZE = 512;
|
||||
const READ_ONLY_EXECUTABLE_MODE = Buffer.from([0xa4, 0x81, 0x00, 0x00]);
|
||||
|
||||
@@ -4,7 +4,7 @@ import { describe, expect, test } from "vitest";
|
||||
import {
|
||||
decodeGitConnectionInput,
|
||||
decodeWorkAttemptExecutionResult,
|
||||
} from "./execution-runtime";
|
||||
} from "./execution-runtime.ts";
|
||||
|
||||
describe("execution runtime contracts", () => {
|
||||
test("accepts one authenticated Gitea connection", async () => {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/* eslint-disable max-classes-per-file -- execution boundary errors live with their schemas. */
|
||||
import { Effect, Schema } from "effect";
|
||||
|
||||
import { GitProvider } from "./git-provider";
|
||||
import { GitProvider } from "./git-provider.ts";
|
||||
|
||||
export type { GitProvider } from "./git-provider";
|
||||
export type { GitProvider } from "./git-provider.ts";
|
||||
|
||||
const Text = Schema.String.check(
|
||||
Schema.makeFilter((value) => value.trim().length > 0, {
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
currentBranch,
|
||||
nodeShell,
|
||||
push,
|
||||
} from "./git-local-runtime";
|
||||
} from "./git-local-runtime.ts";
|
||||
|
||||
const run = <A, E>(eff: Effect.Effect<A, E>) => Effect.runPromise(eff);
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
isProviderHostCompatible,
|
||||
normalizeRepositoryUrl,
|
||||
providerForHost,
|
||||
} from "./git-provider";
|
||||
} from "./git-provider.ts";
|
||||
import {
|
||||
canSafelyReplaceRepository,
|
||||
idempotencyKeyFor,
|
||||
@@ -18,8 +18,8 @@ import {
|
||||
validatePuterOrgName,
|
||||
validatePuterUsername,
|
||||
validateRepositoryName,
|
||||
} from "./git-provisioning";
|
||||
import { isProcessedEvent } from "./git-webhook";
|
||||
} from "./git-provisioning.ts";
|
||||
import { isProcessedEvent } from "./git-webhook.ts";
|
||||
|
||||
describe("git-provider normalization", () => {
|
||||
test("normalizes a standard HTTPS GitHub URL", async () => {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/* eslint-disable max-classes-per-file -- provisioning commands, results, and errors form one validated-command module. */
|
||||
import { Effect, Schema } from "effect";
|
||||
|
||||
import type { GitProvider, ProviderAccount } from "./git-provider";
|
||||
import type { GitProvider, ProviderAccount } from "./git-provider.ts";
|
||||
import {
|
||||
GitProviderError,
|
||||
RepositoryPrivacy,
|
||||
PUTER_GIT_SERVER_URL,
|
||||
} from "./git-provider";
|
||||
} from "./git-provider.ts";
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Shared filters
|
||||
|
||||
@@ -7,8 +7,8 @@ import {
|
||||
createPullRequest,
|
||||
getIssue,
|
||||
listIssues,
|
||||
} from "./git-remote-runtime";
|
||||
import type { GitRemoteConfig, GitRemoteTransport } from "./git-remote-runtime";
|
||||
} from "./git-remote-runtime.ts";
|
||||
import type { GitRemoteConfig, GitRemoteTransport } from "./git-remote-runtime.ts";
|
||||
|
||||
const config: GitRemoteConfig = {
|
||||
baseUrl: "https://git.example.com",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* eslint-disable max-classes-per-file -- webhook event envelopes and errors form one normalized module. */
|
||||
import { Effect, Schema } from "effect";
|
||||
|
||||
import { GitProvider } from "./git-provider";
|
||||
import { GitProvider } from "./git-provider.ts";
|
||||
|
||||
const Text = Schema.String.check(
|
||||
Schema.makeFilter((value) => value.trim().length > 0, {
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
inspectGitWorkspace,
|
||||
makeCommitMessage,
|
||||
validatePullRequestMetadata,
|
||||
} from "./git";
|
||||
} from "./git.ts";
|
||||
|
||||
const inspectionInput = {
|
||||
branch: "work/issue-5",
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
projectIssueDraftFromSignal,
|
||||
queueProjectIssue,
|
||||
validateProjectIssueDraft,
|
||||
} from "./project-issue";
|
||||
} from "./project-issue.ts";
|
||||
|
||||
describe("project issue primitives", () => {
|
||||
it("normalizes an explicit project request", () => {
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
getProjectWorkNextAction,
|
||||
getProjectWorkProgress,
|
||||
getProjectWorkStatus,
|
||||
} from "./project-work";
|
||||
} from "./project-work.ts";
|
||||
|
||||
describe("project work state mapping", () => {
|
||||
test("maps issue and run statuses to the same product language", () => {
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
WorkspaceExecutionError,
|
||||
WorkspaceStateError,
|
||||
WorkspaceValidationError,
|
||||
} from "./project-workspace";
|
||||
} from "./project-workspace.ts";
|
||||
|
||||
const makeInput = () => ({
|
||||
artifacts: [
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/* eslint-disable max-classes-per-file -- deep Effect v4 domain module: branded schemas, tagged errors, and context services */
|
||||
import { Context, Effect, Layer, Schema } from "effect";
|
||||
|
||||
import { OrganizationId, ProjectId, TimestampMs } from "./signal";
|
||||
import { OrganizationId, ProjectId, TimestampMs } from "./signal.ts";
|
||||
|
||||
export type { OrganizationId, ProjectId } from "./signal";
|
||||
export type { OrganizationId, ProjectId } from "./signal.ts";
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Domain constants
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Effect } from "effect";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { composeSignal, SignalValidationError } from "./signal";
|
||||
import type { SignalValidationReason } from "./signal";
|
||||
import { composeSignal, SignalValidationError } from "./signal.ts";
|
||||
import type { SignalValidationReason } from "./signal.ts";
|
||||
|
||||
type TestSignalScope =
|
||||
| {
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
redactSmokeText,
|
||||
selectSmokeModelRoles,
|
||||
validateSmokeCapabilities,
|
||||
} from "./smoke";
|
||||
} from "./smoke.ts";
|
||||
|
||||
const validRoleSelection = () => ({
|
||||
plannerReviewerModel: "glm-5.2",
|
||||
|
||||
@@ -4,7 +4,7 @@ import { describe, expect, test } from "vitest";
|
||||
import {
|
||||
decodeWorkArtifactDraft,
|
||||
decodeWorkDeliveryDraft,
|
||||
} from "./work-artifact";
|
||||
} from "./work-artifact.ts";
|
||||
|
||||
describe("Work artifact contracts", () => {
|
||||
test("accepts traceable artifact and delivery metadata", async () => {
|
||||
|
||||
@@ -8,6 +8,7 @@ export const WorkStatus = Schema.Literals([
|
||||
"awaiting-design-approval",
|
||||
"ready",
|
||||
"executing",
|
||||
"verifying",
|
||||
"needs-input",
|
||||
"blocked",
|
||||
"completed",
|
||||
@@ -19,15 +20,16 @@ export type WorkStatus = typeof WorkStatus.Type;
|
||||
export const WORK_TRANSITIONS: Readonly<
|
||||
Record<WorkStatus, readonly WorkStatus[]>
|
||||
> = {
|
||||
"awaiting-definition-approval": ["designing", "defining"],
|
||||
"awaiting-design-approval": ["ready", "designing"],
|
||||
blocked: ["ready", "executing", "cancelled"],
|
||||
"awaiting-definition-approval": ["defining", "cancelled"],
|
||||
"awaiting-design-approval": ["designing", "cancelled"],
|
||||
blocked: ["ready", "defining", "designing", "executing", "cancelled"],
|
||||
cancelled: ["ready"],
|
||||
completed: [],
|
||||
defining: ["awaiting-definition-approval", "proposed"],
|
||||
designing: ["awaiting-design-approval", "awaiting-definition-approval"],
|
||||
defining: ["designing", "proposed"],
|
||||
designing: ["ready", "defining"],
|
||||
executing: [
|
||||
"ready",
|
||||
"verifying",
|
||||
"needs-input",
|
||||
"blocked",
|
||||
"completed",
|
||||
@@ -38,6 +40,14 @@ export const WORK_TRANSITIONS: Readonly<
|
||||
"needs-input": ["ready", "executing", "cancelled"],
|
||||
proposed: ["defining"],
|
||||
ready: ["executing", "designing", "cancelled"],
|
||||
verifying: [
|
||||
"ready",
|
||||
"executing",
|
||||
"completed",
|
||||
"blocked",
|
||||
"failed",
|
||||
"cancelled",
|
||||
],
|
||||
};
|
||||
|
||||
export const canTransitionWork = (from: WorkStatus, to: WorkStatus): boolean =>
|
||||
@@ -51,15 +61,3 @@ export const assertWorkTransition = (
|
||||
throw new Error(`Invalid Work transition: ${from} -> ${to}`);
|
||||
}
|
||||
};
|
||||
|
||||
export const definitionRevisionInvalidation = {
|
||||
definitionApproval: "invalidate" as const,
|
||||
dependentDesign: "invalidate" as const,
|
||||
designApproval: "invalidate" as const,
|
||||
workStatus: "defining" as const,
|
||||
};
|
||||
|
||||
export const designRevisionInvalidation = {
|
||||
designApproval: "invalidate" as const,
|
||||
workStatus: "designing" as const,
|
||||
};
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
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";
|
||||
import { FakeHarnessLive } from "./harness-runtime.ts";
|
||||
import { defaultCodingKitV0, resolveOutcome, shouldRetry } from "./resolver.ts";
|
||||
import { decodeDefinition, validateDefinition } from "./work-definition.ts";
|
||||
import { validateDesignPacket } from "./work-design.ts";
|
||||
import { canTransitionWork } from "./work-lifecycle.ts";
|
||||
|
||||
const definition = {
|
||||
acceptanceCriteria: ["terminal outcome"],
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
signalAttachedEvent,
|
||||
workDraftFromSignal,
|
||||
workProposedEventFromSignal,
|
||||
} from "./work";
|
||||
} from "./work.ts";
|
||||
|
||||
describe("workDraftFromSignal", () => {
|
||||
test("creates a proposed Work draft from Signal meaning", async () => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Array as EffectArray, Effect, Order, Schema } from "effect";
|
||||
|
||||
export { WorkStatus } from "./work-lifecycle";
|
||||
export type { WorkStatus as WorkLifecycleStatus } from "./work-lifecycle";
|
||||
export { WorkStatus } from "./work-lifecycle.ts";
|
||||
export type { WorkStatus as WorkLifecycleStatus } from "./work-lifecycle.ts";
|
||||
|
||||
const MeaningfulString = Schema.String.check(
|
||||
Schema.makeFilter((value) => value.trim().length > 0, {
|
||||
@@ -92,18 +92,15 @@ export const WorkEventKind = Schema.Literals([
|
||||
"work.proposed",
|
||||
"signal.attached",
|
||||
"definition.requested",
|
||||
"definition.approved",
|
||||
"definition.saved",
|
||||
"definition.revised",
|
||||
"definition.approved",
|
||||
"definition.invalidated",
|
||||
"question.created",
|
||||
"question.answered",
|
||||
"question.withdrawn",
|
||||
"design.requested",
|
||||
"design.saved",
|
||||
"design.revised",
|
||||
"design.approved",
|
||||
"design.invalidated",
|
||||
"design.revised",
|
||||
"planner.failed",
|
||||
"slice.started",
|
||||
"slice.completed",
|
||||
@@ -116,6 +113,9 @@ export const WorkEventKind = Schema.Literals([
|
||||
"attempt.completed",
|
||||
"attempt.reconciled",
|
||||
"resolver.decided",
|
||||
"verification.started",
|
||||
"verification.completed",
|
||||
"verification.failed",
|
||||
"artifact.recorded",
|
||||
"delivery.recorded",
|
||||
"delivery.updated",
|
||||
|
||||
Reference in New Issue
Block a user