Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
22 changes: 6 additions & 16 deletions apps/decodex/src/workflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,6 @@ pub struct WorkflowExecution {
max_attempts: u32,
max_turns: u32,
max_retry_backoff_ms: u64,
#[serde(default)]
max_concurrent_agents: WorkflowConcurrencyLimit,
canonicalize_commands: Vec<String>,
verify_commands: Vec<String>,
Expand Down Expand Up @@ -568,10 +567,9 @@ impl<'de> Visitor<'de> for WorkflowConcurrencyLimitVisitor {
}

/// Project-level concurrent agent limit.
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum WorkflowConcurrencyLimit {
/// No project-level concurrent-agent cap.
#[default]
Unlimited,
/// A positive project-level concurrent-agent cap.
Limited(u32),
Expand Down Expand Up @@ -1406,6 +1404,11 @@ transport = "stdio://"
"agent",
),
("missing max_attempts", Remove("max_attempts = 3\n"), "max_attempts"),
(
"missing max_concurrent_agents",
Remove("max_concurrent_agents = 1\n"),
"max_concurrent_agents",
),
(
"empty terminal states",
Replace(
Expand Down Expand Up @@ -1757,19 +1760,6 @@ Then validate the lane.
);
}

#[test]
fn defaults_missing_global_concurrency_limit_to_unlimited() {
let document = parse_valid_workflow_with(|markdown| {
*markdown = markdown.replace("max_concurrent_agents = 1\n", "");
})
.expect("missing global concurrency should parse");

assert_eq!(
document.frontmatter().execution().max_concurrent_agents(),
WorkflowConcurrencyLimit::Unlimited
);
}

#[test]
fn rejects_zero_global_concurrency_limit() {
let result = WorkflowDocument::parse_markdown(
Expand Down
2 changes: 1 addition & 1 deletion docs/runbook/self-dogfood-pilot.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ At minimum, the target repo should define:
- `[execution] max_attempts`
- `[execution] max_turns`
- `[execution] max_retry_backoff_ms`
- optional `[execution] max_concurrent_agents`; omit it, or set it to `"unlimited"`, to run without a project-level concurrent-agent cap
- `[execution] max_concurrent_agents`; set it explicitly to `"unlimited"` to run without a project-level concurrent-agent cap
- optional `[context] read_first = [...]` only when the repo truly needs extra repo-local files loaded in addition to the `WORKFLOW.md` body; treat this as a Decodex-local extension, not as the primary policy surface

Child-run execution policy is not part of the project-owned `WORKFLOW.md` contract. `decodex` must let `codex app-server` inherit sandbox and approval behavior from the active Codex runtime instead of pinning repo-local overrides.
Expand Down
2 changes: 1 addition & 1 deletion docs/spec/runtime.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ Optional future expansion:

Current runtime note:

- Project-level concurrency is unlimited by default; a project may opt into a finite cap with `[execution] max_concurrent_agents = <positive integer>`.
- Project-level concurrency must be explicit; set `[execution] max_concurrent_agents = "unlimited"` for no project-level cap, or use a positive integer for a finite cap.
- Active leases are the service-local claim set for running lanes, and shared dispatch-slot locks coordinate cross-process capacity when a finite cap is configured.

## Lane model
Expand Down
5 changes: 2 additions & 3 deletions docs/spec/workflow-file.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,8 @@ Supported keys:
- note: caps control-plane-owned failure retry backoff in milliseconds; clean continuation retries use a separate short fixed delay in runtime policy
- `max_concurrent_agents`
- type: integer or string `"unlimited"`
- optional
- default: `"unlimited"`
- note: when set to a positive integer, upper-bounds concurrent `decodex` runs per repository; when omitted or set to `"unlimited"`, Decodex does not apply a project-level concurrent-agent cap; Decodex does not apply separate per-state concurrency caps
- required
- note: set to `"unlimited"` to run without a project-level concurrent-agent cap; when set to a positive integer, upper-bounds concurrent `decodex` runs per repository; Decodex does not apply separate per-state concurrency caps
- `canonicalize_commands`
- type: array of string
- required
Expand Down