Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
ebf1b31
docs: define v0 organization contracts
May 25, 2026
9d1ffa5
docs: propose package-first organization architecture
May 25, 2026
383e47d
docs: ground organization CA in cluster runtime
May 25, 2026
5f6598c
docs: define organization event automation
May 25, 2026
5a68e89
feat(agentic-org): add supervisor signal runtime slice
May 25, 2026
584d0d8
feat(agentic-org): add workflow visibility contract
May 25, 2026
2c33734
refactor(agentic-org): invert command state and handler composition
May 25, 2026
33dd42a
merge(main): refresh PR #4990 against current main
May 25, 2026
fa366b2
feat(agentic-org): add Cockroach state adapter foundation
May 25, 2026
47fc64d
feat(agentic-org): add NATS outbox publisher contract
May 25, 2026
16417ae
refactor(agentic-org): keep durable state adapter replaceable
May 25, 2026
24c30bc
refactor(agentic-org): separate package tests from source
May 25, 2026
86c2d58
merge(main): refresh agentic organization branch
May 25, 2026
9fe66ed
feat(agentic-org): add inbound event ingestion spine
May 26, 2026
c9f3d18
feat(agentic-org): add worker composition host
May 26, 2026
3beb12f
feat(agentic-org): add NATS inbound consumer adapter
May 26, 2026
cde22a7
feat(agentic-org): add workers app runtime host
May 26, 2026
77f3fd7
feat(agentic-org): add workers process composition seam
May 26, 2026
0975a44
fix(agentic-org): preserve worker visibility on telemetry failure
May 26, 2026
0e14b4e
docs(agentic-org): add north star alignment checkpoint
May 26, 2026
cebc1f8
feat(agentic-org): add transactional outcome ports
May 26, 2026
2ae3c71
fix(agentic-org): keep idempotency races behind generic ports
May 26, 2026
680c75b
Merge remote-tracking branch 'origin/main' into codex/agentic-org-pac…
May 26, 2026
6a1975d
fix(agentic-org): harden inbound failure races
May 26, 2026
85770e1
Merge remote-tracking branch 'origin/main' into codex/agentic-org-pac…
May 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions agentic-organization/apps/workers/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Agentic Organization Workers App

`apps/workers` is the first runtime-host shell for Agentic
Organization. It is intentionally small and NodeNext-first so the
process boundary can be tested before NestJS, real NATS clients,
CockroachDB connection pools, Kubernetes manifests, or process
supervisors are introduced.

## Responsibility

The app composes existing packages. It does not own business rules.

Current duties:

- parse typed runtime configuration from process environment values that
Kubernetes can later provide through ConfigMaps and Secrets;
- compose the runtime through a single app-level factory so concrete
adapters stay outside domain and package code;
- run the package-level Organization worker cycle;
- run the NATS JetStream consumer adapter cycle;
- pass configured NATS batch size, stream name, and durable consumer
name into the adapter boundary;
- emit worker-cycle and NATS-consumer batch telemetry records;
- return a healthy/degraded runtime result that makes failures visible
without starving the other loop.

## Boundary

`apps/workers` may bind adapter packages and process configuration.
Packages must not import this app.

The app currently receives ports that tests can fake:

- `OrganizationWorkerHost`;
- `NatsJetStreamEventConsumer`;
- `WorkerRuntimeTelemetrySink`.

Future concrete process wiring can bind these ports to CockroachDB,
NATS, OTLP/logging, health checks, readiness checks, and graceful
shutdown without changing runtime rule evaluation.

## Environment

The worker app owns process configuration. Packages receive typed
config and ports; they do not read environment variables.

Required runtime values:

- `AGENTIC_ORG_ENV`;
- `AGENTIC_ORG_ID`;
- `NATS_STREAM`;
- `NATS_DURABLE`;
- `NATS_INBOUND_BATCH_SIZE`.

URLs, credentials, and other sensitive adapter settings belong in later
adapter config bound by the composition root. They should come from
Kubernetes Secrets or ExternalSecrets in the full AI cluster, not from
domain packages.

## Composition Root

`composeWorkerRuntime` is the app-level seam where already-constructed
ports are connected to the runtime. Today tests provide fake ports. The
next production slice should construct real CockroachDB, NATS, and
telemetry adapters here while preserving the same package contracts.
28 changes: 28 additions & 0 deletions agentic-organization/apps/workers/src/composition.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import type { NatsJetStreamEventConsumer } from "../../../packages/messaging-nats/src/index.ts";
import type { OrganizationWorkerHost } from "../../../packages/workers/src/index.ts";
import {
createWorkerRuntime,
type WorkerRuntime,
type WorkerRuntimeConfig,
type WorkerRuntimeTelemetrySink,
} from "./worker-runtime.ts";

export type WorkerRuntimePorts = {
organizationWorkerHost: OrganizationWorkerHost;
natsEventConsumer: NatsJetStreamEventConsumer;
telemetrySink: WorkerRuntimeTelemetrySink;
};

export type ComposeWorkerRuntimeInput = {
config: WorkerRuntimeConfig;
ports: WorkerRuntimePorts;
};

export function composeWorkerRuntime(input: ComposeWorkerRuntimeInput): WorkerRuntime {
return createWorkerRuntime({
config: input.config,
organizationWorkerHost: input.ports.organizationWorkerHost,
natsEventConsumer: input.ports.natsEventConsumer,
telemetrySink: input.ports.telemetrySink,
});
}
71 changes: 71 additions & 0 deletions agentic-organization/apps/workers/src/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { WorkerRuntimeConfigError, WorkerRuntimeConfigErrorCode, type WorkerRuntimeConfig } from "./worker-runtime.ts";

const decimalIntegerPattern = /^[0-9]+$/;

export const WorkerProcessEnvName = {
AgenticOrgEnv: "AGENTIC_ORG_ENV",
AgenticOrgId: "AGENTIC_ORG_ID",
NatsDurable: "NATS_DURABLE",
NatsInboundBatchSize: "NATS_INBOUND_BATCH_SIZE",
NatsStream: "NATS_STREAM",
} as const;

export type WorkerProcessEnvName = (typeof WorkerProcessEnvName)[keyof typeof WorkerProcessEnvName];

export type WorkerProcessEnvironment = Partial<Record<WorkerProcessEnvName, string | undefined>>;

export function parseWorkerRuntimeConfigFromEnv(env: WorkerProcessEnvironment): WorkerRuntimeConfig {
return {
environment: readRequiredEnvValue(
env,
WorkerProcessEnvName.AgenticOrgEnv,
WorkerRuntimeConfigErrorCode.MissingEnvironment,
),
organizationId: readRequiredEnvValue(
env,
WorkerProcessEnvName.AgenticOrgId,
WorkerRuntimeConfigErrorCode.MissingOrganizationId,
),
natsStreamName: readRequiredEnvValue(
env,
WorkerProcessEnvName.NatsStream,
WorkerRuntimeConfigErrorCode.MissingNatsStreamName,
),
natsDurableName: readRequiredEnvValue(
env,
WorkerProcessEnvName.NatsDurable,
WorkerRuntimeConfigErrorCode.MissingNatsDurableName,
),
natsInboundBatchSize: parseNatsInboundBatchSize(env[WorkerProcessEnvName.NatsInboundBatchSize]),
};
}

function readRequiredEnvValue(
env: WorkerProcessEnvironment,
name: WorkerProcessEnvName,
errorCode: WorkerRuntimeConfigErrorCode,
): string {
const value = env[name];

if (value === undefined || value.trim().length === 0) {
throw new WorkerRuntimeConfigError(errorCode);
}

return value.trim();
}

function parseNatsInboundBatchSize(value: string | undefined): number {
const trimmedValue = value?.trim();

if (trimmedValue === undefined || trimmedValue.length === 0 || !decimalIntegerPattern.test(trimmedValue)) {
throw new WorkerRuntimeConfigError(WorkerRuntimeConfigErrorCode.InvalidNatsInboundBatchSize);
}

const parsedValue = Number(trimmedValue);

if (!Number.isSafeInteger(parsedValue) || parsedValue < 1) {
throw new WorkerRuntimeConfigError(WorkerRuntimeConfigErrorCode.InvalidNatsInboundBatchSize);
}

return parsedValue;
}
18 changes: 18 additions & 0 deletions agentic-organization/apps/workers/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export { WorkerProcessEnvName, parseWorkerRuntimeConfigFromEnv, type WorkerProcessEnvironment } from "./config.ts";
export { composeWorkerRuntime, type ComposeWorkerRuntimeInput, type WorkerRuntimePorts } from "./composition.ts";
export {
WorkerRuntimeConfigError,
WorkerRuntimeConfigErrorCode,
WorkerRuntimeFailureStage,
WorkerRuntimeStatus,
WorkerRuntimeTelemetryEventName,
createWorkerRuntime,
type CreateWorkerRuntimeInput,
type WorkerRuntime,
type WorkerRuntimeConfig,
type WorkerRuntimeFailure,
type WorkerRuntimeRunResult,
type WorkerRuntimeTelemetryAttributes,
type WorkerRuntimeTelemetryRecord,
type WorkerRuntimeTelemetrySink,
} from "./worker-runtime.ts";
Loading
Loading