From aeeb1bbd5434ee9fb8ba457ad5187a4cd44d7478 Mon Sep 17 00:00:00 2001 From: Rafael Bittencourt Date: Sun, 13 Sep 2026 02:44:45 -0300 Subject: [PATCH] feat: add adaptive native waits (#5) --- CONTRIBUTING.md | 5 ++ README.md | 7 +- .../advanced-delivery/AGENTS.snippet.md | 3 +- .../AGENTS.with-skill.snippet.md | 3 +- arrangements/advanced-delivery/README.md | 6 ++ .../advanced-delivery/arrangement.toml | 2 +- arrangements/advanced-delivery/config.toml | 2 + .../balanced-delivery/AGENTS.snippet.md | 3 +- .../AGENTS.with-skill.snippet.md | 3 +- arrangements/balanced-delivery/README.md | 6 ++ .../balanced-delivery/arrangement.toml | 2 +- arrangements/balanced-delivery/config.toml | 2 + arrangements/lean-delivery/AGENTS.snippet.md | 3 +- .../AGENTS.with-skill.snippet.md | 3 +- arrangements/lean-delivery/README.md | 6 ++ arrangements/lean-delivery/arrangement.toml | 2 +- arrangements/lean-delivery/config.toml | 2 + docs/CHANGELOG.md | 11 +++ docs/configuration.md | 29 ++++++++ docs/installation.md | 27 ++++++- docs/orchestration.md | 70 +++++++++++++++++++ docs/validation.md | 23 ++++++ scripts/validate_catalog.py | 28 +++++++- skills/codex-orchestration/SKILL.md | 12 +++- tests/test_catalog.py | 42 +++++++++++ 25 files changed, 288 insertions(+), 14 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ace6fd3..feca554 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -59,6 +59,11 @@ personal paths. The required thread cap is features.multi_agent_v2.max_concurrent_threads_per_session; the optional root agents table may contain only default subagent model and reasoning-effort values. +The V2 table also accepts optional `min_wait_timeout_ms`, `default_wait_timeout_ms` +and `max_wait_timeout_ms`. Values must be integers from 0 through 3600000; after +applying native defaults, minimum <= default <= maximum must hold. See +[configuration](docs/configuration.md#native-child-wait-settings). Explain any +different choice without claiming unmeasured token savings. An optional hook is a contained relative directory with a README.md documenting installation, supported runtime and entrypoint; its implementation may use any supported language and does not require a guard.py file. diff --git a/README.md b/README.md index 6cec624..5a651c7 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ third-party orchestration service to use these files. [Skills](skills/README.md) · [Plugins](plugins/README.md) · [Validation and compatibility](docs/validation.md) -Version 0.2.1 is a community preview. Historical hook and selected-role tests are +Version 0.3.0 is a community preview. Historical hook and selected-role tests are recorded; the revised allocations and caps are not fully runtime-certified. ## Choose an arrangement @@ -26,6 +26,11 @@ The three arrangements provide progressively smaller role catalogs and enable Multi-Agent V2. Roles are available choices, not agents started together. Allocate only useful, independent work; parallel calls consume additional model tokens. +All three use a one-minute minimum and five-minute default for native child +waits. [Adaptive waiting](docs/orchestration.md#adaptive-waiting) explains how to +choose task-appropriate windows and reduce empty polling without changing budgets. +This is not a measured quota-savings guarantee. + Advanced Delivery targets complex product work and spends more of its model allocation on design, advice, critical review and coupled implementation. Balanced Delivery reserves Astra for advice and coupled implementation, and Sol diff --git a/arrangements/advanced-delivery/AGENTS.snippet.md b/arrangements/advanced-delivery/AGENTS.snippet.md index 201cd12..7ea5a4b 100644 --- a/arrangements/advanced-delivery/AGENTS.snippet.md +++ b/arrangements/advanced-delivery/AGENTS.snippet.md @@ -2,7 +2,7 @@ ### Role selection -- Before delegating or reconciling deliveries, invoke the Skill tool with `codex-orchestration` when installed. If no Skill tool exists, read its `SKILL.md` through the native file-reading interface. If the skill is not installed, follow the rules below. +- Before delegating, coordinating ongoing work, or reconciling deliveries, invoke the Skill tool with `codex-orchestration` when installed. If no Skill tool exists, read its `SKILL.md` through the native file-reading interface. If the skill is not installed, follow the rules below. - Read the relevant live role descriptions and instructions; choose the least resource-intensive role suited to the task and required artifact. Read-only roles never receive implementation work. `list_agents` shows running children, not available roles. ### Dispatch contract @@ -13,6 +13,7 @@ ### Ownership and return +- When only delegated work remains, use task-appropriate native waits; avoid repeated status polling. - Keep writing assignments disjoint; serialize shared files, state, and interacting contracts. - Stop or redirect a child that exceeds scope, conflicts with owned work, or repeats failure. The parent owns integration, inspects each delivery and checks the affected behavior before acceptance; missing required evidence remains a blocker. - Use `followup_task` to resume a suitable completed child; `send_message` only queues a message. A recommended role need not already be running. diff --git a/arrangements/advanced-delivery/AGENTS.with-skill.snippet.md b/arrangements/advanced-delivery/AGENTS.with-skill.snippet.md index 77b2c73..7138f09 100644 --- a/arrangements/advanced-delivery/AGENTS.with-skill.snippet.md +++ b/arrangements/advanced-delivery/AGENTS.with-skill.snippet.md @@ -2,7 +2,7 @@ ### Role selection -- Before delegating or reconciling deliveries, invoke the Skill tool with `codex-orchestration` when installed. If no Skill tool exists, read its `SKILL.md` through the native file-reading interface. If the skill is not installed, follow the rules below. +- Before delegating, coordinating ongoing work, or reconciling deliveries, invoke the Skill tool with `codex-orchestration` when installed. If no Skill tool exists, read its `SKILL.md` through the native file-reading interface. If the skill is not installed, follow the rules below. - Read the relevant live role descriptions and instructions; choose the least resource-intensive role suited to the task and required artifact. Read-only roles never receive implementation work. `list_agents` shows running children, not available roles. ### Dispatch contract @@ -13,6 +13,7 @@ ### Ownership and return +- When only delegated work remains, use task-appropriate native waits; avoid repeated status polling. - Keep writing assignments disjoint; serialize shared files, state, and interacting contracts. - Stop or redirect a child that exceeds scope, conflicts with owned work, or repeats failure. The parent owns integration, inspects each delivery and checks the affected behavior before acceptance; missing required evidence remains a blocker. - Use `followup_task` to resume a suitable completed child; `send_message` only queues a message. A recommended role need not already be running. diff --git a/arrangements/advanced-delivery/README.md b/arrangements/advanced-delivery/README.md index c70f848..383801e 100644 --- a/arrangements/advanced-delivery/README.md +++ b/arrangements/advanced-delivery/README.md @@ -44,4 +44,10 @@ This is an adapted public roster, not a full personal-profile export. Retained r ## Validation status +Revision 0.3.0 adds a one-minute minimum and five-minute default for native child +waits, without changing this roster or cap. Choose explicit waits according to +the task; see [adaptive waiting](../../docs/orchestration.md#adaptive-waiting) +and [upgrade instructions](../../docs/installation.md#upgrading-from-02x). +Configuration checks are not measurements of quota savings or waiting behavior. + Revision 0.2.0 changes allocations and caps. Historical native tests from 0.1.0 do not certify this revision. Full live role coverage, concurrency saturation, and slot release remain unverified; see [the validation record](../../docs/validation.md). Installation still requires account/model availability and compatible runtime checks. diff --git a/arrangements/advanced-delivery/arrangement.toml b/arrangements/advanced-delivery/arrangement.toml index 092de06..4d0d83d 100644 --- a/arrangements/advanced-delivery/arrangement.toml +++ b/arrangements/advanced-delivery/arrangement.toml @@ -1,6 +1,6 @@ schema_version = 1 id = "advanced-delivery" -version = "0.2.1" +version = "0.3.0" author = "Rafael Bittencourt" description = "Advanced Delivery: Complex product delivery with dedicated reasoning for decisions, diagnosis, ordinary review, critical review, and coupled implementation." license = "MIT" diff --git a/arrangements/advanced-delivery/config.toml b/arrangements/advanced-delivery/config.toml index 72e284a..e26dd82 100644 --- a/arrangements/advanced-delivery/config.toml +++ b/arrangements/advanced-delivery/config.toml @@ -7,4 +7,6 @@ multi_agent = true [features.multi_agent_v2] enabled = true tool_namespace = "agents" +min_wait_timeout_ms = 60000 +default_wait_timeout_ms = 300000 max_concurrent_threads_per_session = 5 diff --git a/arrangements/balanced-delivery/AGENTS.snippet.md b/arrangements/balanced-delivery/AGENTS.snippet.md index 201cd12..7ea5a4b 100644 --- a/arrangements/balanced-delivery/AGENTS.snippet.md +++ b/arrangements/balanced-delivery/AGENTS.snippet.md @@ -2,7 +2,7 @@ ### Role selection -- Before delegating or reconciling deliveries, invoke the Skill tool with `codex-orchestration` when installed. If no Skill tool exists, read its `SKILL.md` through the native file-reading interface. If the skill is not installed, follow the rules below. +- Before delegating, coordinating ongoing work, or reconciling deliveries, invoke the Skill tool with `codex-orchestration` when installed. If no Skill tool exists, read its `SKILL.md` through the native file-reading interface. If the skill is not installed, follow the rules below. - Read the relevant live role descriptions and instructions; choose the least resource-intensive role suited to the task and required artifact. Read-only roles never receive implementation work. `list_agents` shows running children, not available roles. ### Dispatch contract @@ -13,6 +13,7 @@ ### Ownership and return +- When only delegated work remains, use task-appropriate native waits; avoid repeated status polling. - Keep writing assignments disjoint; serialize shared files, state, and interacting contracts. - Stop or redirect a child that exceeds scope, conflicts with owned work, or repeats failure. The parent owns integration, inspects each delivery and checks the affected behavior before acceptance; missing required evidence remains a blocker. - Use `followup_task` to resume a suitable completed child; `send_message` only queues a message. A recommended role need not already be running. diff --git a/arrangements/balanced-delivery/AGENTS.with-skill.snippet.md b/arrangements/balanced-delivery/AGENTS.with-skill.snippet.md index 77b2c73..7138f09 100644 --- a/arrangements/balanced-delivery/AGENTS.with-skill.snippet.md +++ b/arrangements/balanced-delivery/AGENTS.with-skill.snippet.md @@ -2,7 +2,7 @@ ### Role selection -- Before delegating or reconciling deliveries, invoke the Skill tool with `codex-orchestration` when installed. If no Skill tool exists, read its `SKILL.md` through the native file-reading interface. If the skill is not installed, follow the rules below. +- Before delegating, coordinating ongoing work, or reconciling deliveries, invoke the Skill tool with `codex-orchestration` when installed. If no Skill tool exists, read its `SKILL.md` through the native file-reading interface. If the skill is not installed, follow the rules below. - Read the relevant live role descriptions and instructions; choose the least resource-intensive role suited to the task and required artifact. Read-only roles never receive implementation work. `list_agents` shows running children, not available roles. ### Dispatch contract @@ -13,6 +13,7 @@ ### Ownership and return +- When only delegated work remains, use task-appropriate native waits; avoid repeated status polling. - Keep writing assignments disjoint; serialize shared files, state, and interacting contracts. - Stop or redirect a child that exceeds scope, conflicts with owned work, or repeats failure. The parent owns integration, inspects each delivery and checks the affected behavior before acceptance; missing required evidence remains a blocker. - Use `followup_task` to resume a suitable completed child; `send_message` only queues a message. A recommended role need not already be running. diff --git a/arrangements/balanced-delivery/README.md b/arrangements/balanced-delivery/README.md index 5146a0e..1010845 100644 --- a/arrangements/balanced-delivery/README.md +++ b/arrangements/balanced-delivery/README.md @@ -41,4 +41,10 @@ This is an adapted public roster, not a full personal-profile export. Retained r ## Validation status +Revision 0.3.0 adds a one-minute minimum and five-minute default for native child +waits, without changing this roster or cap. Choose explicit waits according to +the task; see [adaptive waiting](../../docs/orchestration.md#adaptive-waiting) +and [upgrade instructions](../../docs/installation.md#upgrading-from-02x). +Configuration checks are not measurements of quota savings or waiting behavior. + Revision 0.2.0 changes allocations and caps. Historical native tests from 0.1.0 do not certify this revision. Full live role coverage, concurrency saturation, and slot release remain unverified; see [the validation record](../../docs/validation.md). Installation still requires account/model availability and compatible runtime checks. diff --git a/arrangements/balanced-delivery/arrangement.toml b/arrangements/balanced-delivery/arrangement.toml index 094e1b5..59f4fbb 100644 --- a/arrangements/balanced-delivery/arrangement.toml +++ b/arrangements/balanced-delivery/arrangement.toml @@ -1,6 +1,6 @@ schema_version = 1 id = "balanced-delivery" -version = "0.2.1" +version = "0.3.0" author = "Rafael Bittencourt" description = "Balanced Delivery: Everyday product delivery with Luna implementing established patterns, Sol handling backend work and integration review, and Astra handling decisions and coupled implementation." license = "MIT" diff --git a/arrangements/balanced-delivery/config.toml b/arrangements/balanced-delivery/config.toml index f40d218..38c4b1c 100644 --- a/arrangements/balanced-delivery/config.toml +++ b/arrangements/balanced-delivery/config.toml @@ -7,4 +7,6 @@ multi_agent = true [features.multi_agent_v2] enabled = true tool_namespace = "agents" +min_wait_timeout_ms = 60000 +default_wait_timeout_ms = 300000 max_concurrent_threads_per_session = 4 diff --git a/arrangements/lean-delivery/AGENTS.snippet.md b/arrangements/lean-delivery/AGENTS.snippet.md index 201cd12..7ea5a4b 100644 --- a/arrangements/lean-delivery/AGENTS.snippet.md +++ b/arrangements/lean-delivery/AGENTS.snippet.md @@ -2,7 +2,7 @@ ### Role selection -- Before delegating or reconciling deliveries, invoke the Skill tool with `codex-orchestration` when installed. If no Skill tool exists, read its `SKILL.md` through the native file-reading interface. If the skill is not installed, follow the rules below. +- Before delegating, coordinating ongoing work, or reconciling deliveries, invoke the Skill tool with `codex-orchestration` when installed. If no Skill tool exists, read its `SKILL.md` through the native file-reading interface. If the skill is not installed, follow the rules below. - Read the relevant live role descriptions and instructions; choose the least resource-intensive role suited to the task and required artifact. Read-only roles never receive implementation work. `list_agents` shows running children, not available roles. ### Dispatch contract @@ -13,6 +13,7 @@ ### Ownership and return +- When only delegated work remains, use task-appropriate native waits; avoid repeated status polling. - Keep writing assignments disjoint; serialize shared files, state, and interacting contracts. - Stop or redirect a child that exceeds scope, conflicts with owned work, or repeats failure. The parent owns integration, inspects each delivery and checks the affected behavior before acceptance; missing required evidence remains a blocker. - Use `followup_task` to resume a suitable completed child; `send_message` only queues a message. A recommended role need not already be running. diff --git a/arrangements/lean-delivery/AGENTS.with-skill.snippet.md b/arrangements/lean-delivery/AGENTS.with-skill.snippet.md index 77b2c73..7138f09 100644 --- a/arrangements/lean-delivery/AGENTS.with-skill.snippet.md +++ b/arrangements/lean-delivery/AGENTS.with-skill.snippet.md @@ -2,7 +2,7 @@ ### Role selection -- Before delegating or reconciling deliveries, invoke the Skill tool with `codex-orchestration` when installed. If no Skill tool exists, read its `SKILL.md` through the native file-reading interface. If the skill is not installed, follow the rules below. +- Before delegating, coordinating ongoing work, or reconciling deliveries, invoke the Skill tool with `codex-orchestration` when installed. If no Skill tool exists, read its `SKILL.md` through the native file-reading interface. If the skill is not installed, follow the rules below. - Read the relevant live role descriptions and instructions; choose the least resource-intensive role suited to the task and required artifact. Read-only roles never receive implementation work. `list_agents` shows running children, not available roles. ### Dispatch contract @@ -13,6 +13,7 @@ ### Ownership and return +- When only delegated work remains, use task-appropriate native waits; avoid repeated status polling. - Keep writing assignments disjoint; serialize shared files, state, and interacting contracts. - Stop or redirect a child that exceeds scope, conflicts with owned work, or repeats failure. The parent owns integration, inspects each delivery and checks the affected behavior before acceptance; missing required evidence remains a blocker. - Use `followup_task` to resume a suitable completed child; `send_message` only queues a message. A recommended role need not already be running. diff --git a/arrangements/lean-delivery/README.md b/arrangements/lean-delivery/README.md index 8926c42..519053d 100644 --- a/arrangements/lean-delivery/README.md +++ b/arrangements/lean-delivery/README.md @@ -37,4 +37,10 @@ This is an adapted public roster, not a full personal-profile export. Retained r ## Validation status +Revision 0.3.0 adds a one-minute minimum and five-minute default for native child +waits, without changing this roster or cap. Choose explicit waits according to +the task; see [adaptive waiting](../../docs/orchestration.md#adaptive-waiting) +and [upgrade instructions](../../docs/installation.md#upgrading-from-02x). +Configuration checks are not measurements of quota savings or waiting behavior. + Revision 0.2.0 changes allocations and caps. Historical native tests from 0.1.0 do not certify this revision. Full live role coverage, concurrency saturation, and slot release remain unverified; see [the validation record](../../docs/validation.md). Installation still requires account/model availability and compatible runtime checks. diff --git a/arrangements/lean-delivery/arrangement.toml b/arrangements/lean-delivery/arrangement.toml index c98e268..8fec714 100644 --- a/arrangements/lean-delivery/arrangement.toml +++ b/arrangements/lean-delivery/arrangement.toml @@ -1,6 +1,6 @@ schema_version = 1 id = "lean-delivery" -version = "0.2.1" +version = "0.3.0" author = "Rafael Bittencourt" description = "Lean Delivery: Cost-conscious, well-bounded delivery with Luna implementing and reviewing, Sol reconciling deliveries, and one Astra advisor for decisions." license = "MIT" diff --git a/arrangements/lean-delivery/config.toml b/arrangements/lean-delivery/config.toml index 76af558..b142d24 100644 --- a/arrangements/lean-delivery/config.toml +++ b/arrangements/lean-delivery/config.toml @@ -7,4 +7,6 @@ multi_agent = true [features.multi_agent_v2] enabled = true tool_namespace = "agents" +min_wait_timeout_ms = 60000 +default_wait_timeout_ms = 300000 max_concurrent_threads_per_session = 3 diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 79a8a55..9189658 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## 0.3.0 — 2026-09-13 + +- Set native child waits to a one-minute minimum and five-minute default in all + three arrangements, preserving budgets, goals, models, caps and hooks. +- Extend the existing optional orchestration skill with task-appropriate waits, + meaningful progress signals and a separate point for investigating a stall. + Keep the installable rules concise. +- Explain context flow, automatic goal continuation, timing tradeoffs, upgrade + and rollback; distinguish configuration evidence from unmeasured quota savings. +- Validate optional wait fields, including types, bounds and effective ordering. + ## 0.2.1 — 2026-09-13 - Keep insertable delegation rules concise: remove roster counts, concurrency diff --git a/docs/configuration.md b/docs/configuration.md index 127b466..1dad439 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -7,10 +7,38 @@ | Lead model and effort | Each arrangement's `config.toml` | Select the root agent; restore the prior fields in your installation to undo a change. | | V2 and namespace | Each arrangement's `config.toml` | Enable the required orchestration tools; revert only installed fields, preserving other feature settings. | | Concurrency cap | Each arrangement's `[features.multi_agent_v2]` table | Bound total active threads, including the lead in the target V2 runtime; consult counting evidence before adjusting. | +| Native child waits | Each arrangement's `[features.multi_agent_v2]` table | Reduce empty wait returns; restore only your previous wait fields to roll back. | | Specialist model, effort and behavior | Each `agents/.toml` | Define one role; restore its reviewed prior revision, not a whole personal config. | | Optional hook command and matcher | `hooks/spawn-contract/hooks.example.json`, adapted at installation | Review and trust the local command; remove only this handler to uninstall. | | Optional skills | `skills//SKILL.md`, declared in each manifest | Delegation and engineering decision procedures; inline triggers in the with-skill snippet include a fallback when absent. | +## Native child wait settings + +All three arrangements use the same wait settings in version 0.3.0: + +| Field under `features.multi_agent_v2` | Native baseline | Catalog value | Meaning | +| --- | --- | --- | --- | +| `min_wait_timeout_ms` | 10000 (10 seconds) | 60000 (1 minute) | Floor for an explicitly requested child wait; shorter requests are raised to this value. | +| `default_wait_timeout_ms` | 30000 (30 seconds) | 300000 (5 minutes) | Used only when the child wait omits its timeout. | +| `max_wait_timeout_ms` | 3600000 (1 hour) | Not overridden | Largest permitted request; a larger request is rejected, not clamped. | + +These are event-aware waits, not mandatory delays: queued child messages and user +input can end a wait early. A requested 30-second wait becomes one minute, not +five minutes. They do not change terminal polling, code-mode waits, goal budgets, +goal continuation, child execution time or the account's usage limits. + +The validator permits optional integer wait fields from 0 through 3600000, +including zero, matching the inspected runtime. Effective values, including +omitted native defaults, must satisfy minimum <= default <= maximum. Setting +only a 60000 minimum is invalid against the native 30000 default; merge both +published fields. An existing maximum below 300000 needs deliberate reconciliation. + +Defaults and behavior were inspected on 2026-09-13 in the pinned upstream +[configuration implementation](https://github.com/openai/codex/blob/dfaf451426868c22e6859f5494150fd6338c3257/codex-rs/core/src/config/mod.rs) +and [V2 wait handler](https://github.com/openai/codex/blob/dfaf451426868c22e6859f5494150fd6338c3257/codex-rs/core/src/tools/handlers/multi_agents_v2/wait.rs). +Check the installed runtime after upgrades. See [adaptive waiting](orchestration.md#adaptive-waiting) +for task-based choices and limitations; these values are not a measured optimum. + ## Baseline There are no runtime package dependencies. Python 3.11+ runs the validator, @@ -35,5 +63,6 @@ and [default nickname selection](https://github.com/openai/codex/blob/b979d4f1f0 | Version | Change | Reason | Rollback | | --- | --- | --- | --- | +| 0.3.0 (2026-09-13) | Set one-minute minimum and five-minute default child waits; add adaptive waiting guidance | Reduce empty parent wait returns without changing budgets or the execution topology | Restore only prior wait fields and the affected instruction/skill sections; remove these fields only if they were previously absent. | | 0.2.0 (2026-09-13) | Add Balanced Delivery; rebalance models, reduce catalogs to 15/12/8 roles and total-thread caps to 5/4/3; require parent-mediated routing | Match reasoning to responsibility and reduce selection and coordination overhead | Reinstall reviewed prior role cards and matching snippets/config fields together. Follow the upgrade removal list; preserve credentials and unrelated settings. | | 0.1.0 | Introduce two lead/specialist combinations, V2 fragments and optional spawn contract | Share independently installable delegation arrangements | Remove the selected roles, instruction section and optional components; restore only the original configuration fields. | diff --git a/docs/installation.md b/docs/installation.md index d13e9e0..6a6f4ca 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -5,6 +5,24 @@ the [validation record](validation.md); these packages target Multi-Agent V2 and do not silently fall back to V1. You need access to the named models. Python 3.11+ is needed only for the optional hook and local validation. +## Upgrading from 0.2.x + +Version 0.3.0 keeps the same roles, models and concurrency caps. Merge these two +fields into your existing `[features.multi_agent_v2]` table, without declaring +the table twice: + +```toml +min_wait_timeout_ms = 60000 +default_wait_timeout_ms = 300000 +``` + +Check any existing maximum for compatibility; it must be at least 300000. +Preserve unrelated settings, budgets and goals. Refresh the chosen instruction +snippet and, only if installed, the existing `codex-orchestration` skill. Start a +new session and verify effective settings. To roll back, restore the prior two +fields (remove them if previously absent) and affected instruction sections. +See [configuration](configuration.md#native-child-wait-settings) for semantics. + ## Upgrading from 0.1.0 Copying a smaller roster over the old directory does not remove obsolete cards. @@ -27,6 +45,11 @@ never restore a whole home over newer credentials or unrelated configuration. ## Choose a scope +Prefer inserting the snippet into your user-level `$CODEX_HOME/AGENTS.md` when +you want the same orchestration across projects. Insert it into the project's +root `AGENTS.md` instead when the policy belongs only to that project. Insert a +section, never replace the file or install this repository's maintainer AGENTS.md. + Both snippet variants provide standalone delegation rules and invoke `codex-orchestration` when installed. Choose `AGENTS.with-skill.snippet.md` only when you also want the separate, optional Pragmatic Programmer engineering @@ -84,8 +107,8 @@ independent security sandbox. Copy the chosen directories from `skills/`, including each LICENSE and NOTICE, to the chosen skill location. The manifests list both optional skills: -- `codex-orchestration`: invoke `$codex-orchestration` before bounded delegation - or reconciliation of worker deliveries. +- `codex-orchestration`: invoke `$codex-orchestration` before bounded delegation, + coordinating ongoing work, or reconciliation of worker deliveries. - `pragmatic-programmer`: invoke `$pragmatic-programmer` when choosing a boundary or reversible first step, diagnosing unexplained success, checking duplicated knowledge, or handling shared state and finite resources. diff --git a/docs/orchestration.md b/docs/orchestration.md index 750bb26..90d77e0 100644 --- a/docs/orchestration.md +++ b/docs/orchestration.md @@ -168,6 +168,76 @@ and integration risks. This restriction lives in the snippets and role instructi The spawn-contract hook checks arguments; it does not establish caller ancestry or mechanically guarantee a recursion limit. +## Adaptive waiting + +The lead should work while useful independent work remains. When only delegated +work remains, choose a native event-aware wait using expected duration, +complexity, workload and meaningful progress signals, not file count alone. +Keep this decision in the existing optional `codex-orchestration` skill; the +insertable rules contain only a concise fallback. No new hook is required. + +```text +Useful independent work? -- yes --> advance it + | + no + v +Native wait --> message/result --> act on the new evidence + | + timeout --> investigation due? -- yes --> inspect a concrete signal + | + no --> wait again +``` + +Use the configured five-minute default for ordinary delegated work. A brief +check expected to finish quickly can warrant an explicit one-minute window; +a lengthy build or coupled implementation can warrant a longer supported window. +These are starting points, not fixed task classes. Set a separate, task-appropriate +point to investigate missing progress. A running status or an expired wait is +not proof of progress, failure or a stall. Do not extend waits indefinitely when +expected milestones are missing, or interrupt healthy work after every timeout. + +| Scenario | What changes | +| --- | --- | +| Child completes in 20 seconds | Its queued completion can end the five-minute wait early. | +| Child works silently for eight minutes | The longer default can reduce empty returns to the parent model; it does not shorten the child's work. | +| Parent explicitly requests 30 seconds | The one-minute floor applies; the five-minute default does not. | +| Parent already requests five minutes | No change to that wait. | +| Child emits frequent non-actionable messages | Messages still wake the parent; report blockers, meaningful milestones and final artifacts instead. | +| Child stalls | A longer window can postpone detection; the independent investigation point limits this tradeoff. | +| Parent polls a terminal or code-mode cell | Those tools have separate limits and arguments; these V2 settings do not change them. | + +### Context, tokens and the harness + +The native [wait handler](https://github.com/openai/codex/blob/dfaf451426868c22e6859f5494150fd6338c3257/codex-rs/core/src/tools/handlers/multi_agents_v2/wait.rs) +waits on queue activity or a deadline without sampling the model inside that +wait. Repeated short waits can nevertheless cause repeated parent model calls +after the tool returns. Each sampling step builds input from the parent's own +[conversation history](https://github.com/openai/codex/blob/dfaf451426868c22e6859f5494150fd6338c3257/codex-rs/core/src/session/turn.rs). +That is not equivalent to resending all bytes every time: the +[client](https://github.com/openai/codex/blob/dfaf451426868c22e6859f5494150fd6338c3257/codex-rs/core/src/client.rs) +also supports incremental WebSocket requests. Logical context, transmitted bytes, +cached input and account quota accounting must not be conflated. + +The parent receives explicit child communications and final-result/error notices, +not the child's complete transcript. [Agent listing and completion monitoring](https://github.com/openai/codex/blob/dfaf451426868c22e6859f5494150fd6338c3257/codex-rs/core/src/agent/control.rs) +read status and deliver notifications; listing does not inspect the child's +reasoning or prove progress. `fork_turns: "none"` controls initial parent-to-child +history inheritance, not what results come back. A child still consumes its own +model tokens while the parent waits. Do not assume that ending the parent's turn +guarantees a later completion notice will automatically start another turn. + +Active [goals can automatically continue an idle thread](https://github.com/openai/codex/blob/dfaf451426868c22e6859f5494150fd6338c3257/codex-rs/ext/goal/src/runtime.rs). +The [empty-turn guard](https://github.com/openai/codex/blob/dfaf451426868c22e6859f5494150fd6338c3257/codex-rs/ext/goal/src/accounting.rs) +counts text and tool calls as activity, so it does not identify every unproductive +polling loop. Longer native waits and better instructions mitigate avoidable +returns; they do not change that harness behavior. We have not established a +specific local harness bug or measured a reduction in five-hour quota usage. +Preventing every redundant automatic turn would require a separate upstream +change and regression evidence, not a stronger claim about these settings. + +The source review above is pinned to 2026-09-13. See [configuration](configuration.md#native-child-wait-settings) +for exact values and rollback, and [validation](validation.md) for what was run. + ## Evidence and references ### Prompt and skill design diff --git a/docs/validation.md b/docs/validation.md index 4fddb7f..57a7fbd 100644 --- a/docs/validation.md +++ b/docs/validation.md @@ -9,6 +9,29 @@ or a configured cap alone is not a completed implementation or saturation test. ## Current measured status +### 0.3.0 wait configuration — 2026-09-13 + +On Windows with `codex-cli 0.155.0-alpha.3.10`, three fresh isolated homes loaded +the actual arrangement fragments and all their current role cards. The native +`app-server --stdio --strict-config` accepted each configuration; `config/read` +returned `min_wait_timeout_ms=60000` and `default_wait_timeout_ms=300000` for +Advanced, Balanced and Lean. No credentials were copied and no model turn ran. +The owned process trees exited and the disposable homes were removed. + +Negative control: `codex debug prompt-input` with minimum 400000 and default +300000 exited 1 with `features.multi_agent_v2.default_wait_timeout_ms must be at +least features.multi_agent_v2.min_wait_timeout_ms`. This proves real ordering +validation, not merely successful TOML parsing or silently ignored fields. + +The catalog and component validators passed; all 39 standard-library tests +passed. New regression cases exercise optional fields, native defaults, zero and +upper boundaries, wrong types and invalid effective ordering. The updated skill +also passed its frontmatter validator. These checks do not measure wake latency, +agent adherence, token savings, five-hour quota usage or automatic goal loops. +Native role execution and platform limitations below remain unchanged. + +### Historical role and hook execution + Version 0.1.0 is a community catalog preview, not a certification of every role, platform or concurrency limit. Known integration limits are listed below. diff --git a/scripts/validate_catalog.py b/scripts/validate_catalog.py index 30cf265..d214b5c 100644 --- a/scripts/validate_catalog.py +++ b/scripts/validate_catalog.py @@ -36,6 +36,12 @@ "tool_namespace", "max_concurrent_threads_per_session", } +# Effective defaults in the catalog's pinned Codex V2 baseline. +WAIT_DEFAULTS = { + "min_wait_timeout_ms": 10_000, + "default_wait_timeout_ms": 30_000, + "max_wait_timeout_ms": 3_600_000, +} AGENT_FIELDS = { "default_subagent_model", "default_subagent_reasoning_effort", @@ -287,7 +293,10 @@ def _validate_config(path: Path, root: Path, data: dict[str, Any], errors: list[ if not isinstance(v2, dict): errors.append(f"{label}: features 'multi_agent_v2' must be a table") else: - _keys(v2, V2_FIELDS, label, "features.multi_agent_v2", errors) + _keys( + v2, V2_FIELDS | WAIT_DEFAULTS.keys(), label, + "features.multi_agent_v2", errors, required=V2_FIELDS, + ) if v2.get("enabled") is not True: errors.append(f"{label}: features.multi_agent_v2 'enabled' must be true") if not _text(v2.get("tool_namespace")): @@ -300,6 +309,23 @@ def _validate_config(path: Path, root: Path, data: dict[str, Any], errors: list[ f"{label}: features.multi_agent_v2 " "'max_concurrent_threads_per_session' must be a positive integer" ) + waits = {field: v2.get(field, default) for field, default in WAIT_DEFAULTS.items()} + invalid_waits = [ + field for field, value in waits.items() + if type(value) is not int or not 0 <= value <= 3_600_000 + ] + for field in invalid_waits: + errors.append( + f"{label}: wait timeout '{field}' must be an integer from 0 to 3600000" + ) + if not invalid_waits and not ( + waits["min_wait_timeout_ms"] + <= waits["default_wait_timeout_ms"] + <= waits["max_wait_timeout_ms"] + ): + errors.append( + f"{label}: effective wait timeouts must satisfy minimum <= default <= maximum" + ) agents = data.get("agents") if agents is None: diff --git a/skills/codex-orchestration/SKILL.md b/skills/codex-orchestration/SKILL.md index 4fae0cd..1c7463e 100644 --- a/skills/codex-orchestration/SKILL.md +++ b/skills/codex-orchestration/SKILL.md @@ -1,6 +1,6 @@ --- name: codex-orchestration -description: "Route bounded Codex subagent work from live role availability, use the V2 spawn contract, and reconcile independent deliveries." +description: "Route bounded Codex subagent work, coordinate ongoing tasks with appropriate native waits, and reconcile independent deliveries using live roles and the V2 spawn contract." license: Apache-2.0 --- @@ -39,6 +39,16 @@ Use an action verb that matches the needed result: inspect, implement, test, rev Respect the chosen arrangement's allocation, per-role limits, and configured cap, then confirm the current runtime's resolved limits. A refused spawn is not a reason to idle: continue independent local work and wait only when nothing remains to advance. +## Wait according to the task + +If useful independent work remains, do it. Otherwise, use the native event-aware child wait rather than repeatedly listing agents or asking whether they have finished. Choose a timeout within the runtime's limits using expected duration, task complexity, workload, and observable milestones, not file count alone. Use the configured default for an ordinary wait; choose an explicit shorter or longer window when the task warrants it. Incoming messages or user input can end the wait before its timeout. + +Set a task-appropriate point for investigating missing progress, separate from the wait window. A timeout means no event arrived within that window; a running status does not establish progress. When the investigation point is reached, inspect the relevant status or artifact and ask one focused question if needed; do not endlessly extend waits or interrupt healthy work merely because one window expired. + +Children should report actionable blockers, meaningful milestones, and their final artifact, not periodic messages saying they are still working. The parent receives those communications, not the child's complete transcript. On wake, use the new evidence; query status only when it answers a concrete coordination or diagnostic question. + +Child waits, terminal polls, and code-mode cell waits have separate arguments and limits. Use each tool's live schema, choose a suitable supported wait, and retain ownership of started processes. These instructions do not alter budgets, goal state, permissions, or the harness's automatic continuation behavior. + ## Coordinate and accept Give writing children non-overlapping file or component ownership. Serialize work that shares a file, mutable state, or an interacting contract. Stop or redirect a child that lacks evidence, exceeds its brief, repeats failure, or conflicts with owned work. Only the parent integrates deliveries. If two independent deliveries must combine, use an available integration reviewer before the parent accepts the combined result. High-risk work still needs the independent critical review appropriate to its risk. diff --git a/tests/test_catalog.py b/tests/test_catalog.py index 3267c01..e7c1c00 100644 --- a/tests/test_catalog.py +++ b/tests/test_catalog.py @@ -102,6 +102,48 @@ class CatalogValidatorTests(unittest.TestCase): def validate(self, root: Path) -> validate_catalog.ValidationResult: return validate_catalog.validate_catalog(root) + def test_accepts_optional_wait_windows_and_boundary_values(self) -> None: + for fields in ( + "min_wait_timeout_ms = 60000\ndefault_wait_timeout_ms = 300000", + "max_wait_timeout_ms = 30000", + "min_wait_timeout_ms = 0\ndefault_wait_timeout_ms = 0\nmax_wait_timeout_ms = 0", + "min_wait_timeout_ms = 3600000\ndefault_wait_timeout_ms = 3600000", + ): + with self.subTest(fields=fields), tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + config = build_catalog(root) / "config.toml" + config.write_text( + config.read_text(encoding="utf-8").replace( + "[agents]", f"{fields}\n\n[agents]" + ), + encoding="utf-8", + ) + self.assertEqual([], self.validate(root).errors) + + def test_rejects_invalid_wait_types_ranges_and_effective_order(self) -> None: + for fields in ( + "min_wait_timeout_ms = true", + 'default_wait_timeout_ms = "300000"', + "default_wait_timeout_ms = 300000.0", + "max_wait_timeout_ms = -1", + "max_wait_timeout_ms = 3600001", + "min_wait_timeout_ms = 60000", + "max_wait_timeout_ms = 20000", + "min_wait_timeout_ms = 60000\nmax_wait_timeout_ms = 50000", + ): + with self.subTest(fields=fields), tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + config = build_catalog(root) / "config.toml" + config.write_text( + config.read_text(encoding="utf-8").replace( + "[agents]", f"{fields}\n\n[agents]" + ), + encoding="utf-8", + ) + errors = "\n".join(self.validate(root).errors) + self.assertIn("wait timeout", errors) + self.assertNotIn("unsupported key", errors) + def test_accepts_complete_catalog_and_reports_counts(self) -> None: with tempfile.TemporaryDirectory() as temporary: root = Path(temporary)