Skip to content

feat(playbook): route DAG nodes through generated harness - #558

Merged
ypflll merged 8 commits into
mainfrom
refactor/participant_full_roster
Sep 21, 2026
Merged

ypflll merged 8 commits into
mainfrom
refactor/participant_full_roster

Conversation

@ypflll

@ypflll ypflll commented Sep 20, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Expose the generated per-turn Worker Table on spawn, run_subagent_dag, and resolve_dag_node, and resolve each label before roster and capability validation.
  • Freeze each generated worker brief and charter payload into the public DAG node backend so foreground and background runs preserve the same contract as spawn.
  • Keep stored Playbook DAGs isolated from the turn Worker Table. A stored node whose agent name matches a generated label now retains its authored agent, prompt, tools, and checks.
  • Preserve compatibility with legacy backend run signatures, make backend wrappers safe to copy, and share the named tool-choice conversion across both Responses transports.
  • Keep playbooks.enabled as the master switch for Harness generation.

Type

  • Fix
  • Feature
  • Docs
  • CI / tooling
  • Refactor
  • Other

Verification

  • Relevant tests pass locally
  • Relevant lint / type checks pass locally
  • User-facing docs or screenshots are updated when needed

Commands and results:

  • uv run pytest tests/test_agent_playbook_delegate.py tests/test_playbook_executor.py tests/test_openai_codex_provider.py tests/test_subagent_dag_core.py tests/test_subagent_dag_control_tools.py tests/test_subagent_dag_runner.py tests/integration/test_agent_playbook_e2e.py tests/integration/test_participant_roster_e2e.py -q - 613 passed after rebasing onto current main.
  • uv run pytest tests/test_agent_playbook_delegate.py tests/test_openai_codex_provider.py -q - 66 passed, including a blocking stored-Playbook DAG execution with a colliding turn worker label and a Codex request-body assertion.
  • uv run ruff check . - passed.
  • uv run ty check raven/agent/subagent/dag_tool.py raven/agent/loop/wiring.py raven/providers/openai_responses_provider.py - passed.
  • uv run pytest -q - 23,523 passed and 122 skipped. Three failures were outside this PR diff; isolated reruns passed the research-tool case, while the CLI theme ANSI expectation and install-script PATH fixture remained reproducible and unrelated.
  • Real Codex E2E on the feature branch generated two distinct Harness workers, exposed their aliases to the DAG planner, applied both charters, and completed both nodes. The disabled-path E2E made zero Harness setup calls and completed through the default roster.

CONTEXT.md now documents all live Worker Table surfaces and the stored-Playbook isolation boundary. No screenshots are needed because the public configuration shape and UI are unchanged.

Risk

  • Security impact considered
  • Backward compatibility considered
  • Rollback path is clear for risky changes

The generated Worker Table still narrows capabilities only; it cannot widen the target agent permissions. Public model-authored DAGs read the current turn table, while the private stored-Playbook DAG receives an explicit empty source. With no generated table, existing roster behavior is unchanged.

Rollback is a revert of this PR. Operators can also disable the generated Harness path with playbooks.enabled: false.

Related Issues

N/A

@ypflll
ypflll requested a review from LivXue as a code owner September 20, 2026 13:11

@gloryfromca gloryfromca left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blockers; this can merge as far as I am concerned.

I reviewed github/main...HEAD and the prospective merge tree. Coverage included the repository rules and relevant CONTEXT.md Harness/Worker Table contracts; the diff; participant, DAG schema/preflight/runner/control, playbook-generation, and provider callers; branch history; backward compatibility for disabled/default playbook paths; and the test changes for weakening (none found). The participant-roster portion is already byte-identical on current main; the effective new merge delta is the DAG worker delegation, master-switch guard, and Codex Responses tool-choice conversion.

Verification:

  • uv run pytest tests/test_agent_playbook_delegate.py tests/test_openai_codex_provider.py tests/test_subagent_dag_core.py tests/test_subagent_dag_control_tools.py tests/integration/test_agent_playbook_e2e.py tests/integration/test_participant_roster_e2e.py -q - 293 passed.
  • uv run pytest tests/test_participant_hook.py tests/test_subagent_dag_runner.py tests/test_subagent_dag_mcp_scope.py tests/test_plugin_runtime_binding.py tests/test_agent_loop_playbook_entry.py -q - 325 passed, 3 failed because the optional everos-memory distribution is not installed; all three are the memory-recorder cases and the run reports that missing backend explicitly.
  • uv run ruff check on the effective changed Python files and tests - passed.
  • uv run ty check on the effective changed source files - passed.
  • git merge-tree --write-tree github/main HEAD - clean.
  • GitHub CI - all reported checks pass.

@gloryfromca gloryfromca left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blockers; this can merge as far as I am concerned.

This revision only merges current main. I compared it with the previously reviewed 3331bdc2ab20: the five-file PR diff is unchanged, the three authored commits match one-for-one in the range-diff, and the merge contains no conflict-resolution edits in the Harness, DAG, playbook-generation, or Codex provider paths. I rechecked the repository rules and relevant CONTEXT.md contracts, affected callers, history, backward-compatible disabled/default paths, architecture boundaries, and test changes; nothing new weakens coverage or changes the prior conclusion.

Verification on e74c12b71feb:

  • uv run pytest tests/test_agent_playbook_delegate.py tests/test_openai_codex_provider.py tests/test_subagent_dag_core.py tests/test_subagent_dag_control_tools.py tests/integration/test_agent_playbook_e2e.py tests/integration/test_participant_roster_e2e.py -q - 293 passed.
  • Completed GitHub checks are green; the four unit shards were still pending when reviewed.

@gloryfromca gloryfromca left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blockers; this can merge as far as I am concerned.

This revision only merges the latest documentation-only main commit. I refreshed github/main and confirmed that the effective five-file PR diff and all three authored commits remain identical; the merge adds no conflict-resolution edits or interactions with the Harness, DAG, playbook-generation, or Codex provider paths. For this delta I rechecked repository rules, relevant architecture contracts, callers and history, backward compatibility, and test coverage; no tests were weakened and no prior conclusion changed.

Verification on f0ca4db7d0f3: the focused Harness, playbook delegation, Codex provider, DAG core/control, and integration suite passed 293 tests. Completed GitHub checks are green; four unit shards were still pending when reviewed.

@LivXue

LivXue commented Sep 20, 2026

Copy link
Copy Markdown
Member

Reviewed at head f0ca4db7. The effective change is 5 files (+197/-7): raven/agent/loop/wiring.py, raven/agent/subagent/dag_tool.py, raven/providers/openai_codex_provider.py, and the two test files. The branch's other two commits (df6ea206, 91f2301b) are already on main via #532, so they add nothing to the merge.

Tests, run against the PR tree: tests/test_agent_playbook_delegate.py + tests/test_openai_codex_provider.py -> 62 passed; a 25-file agent / DAG / tool-registry / playbook subset -> 1228 passed. The branch is 5 commits ahead of main and 0 behind, and the merge adds only those five files.

One substantive finding, four small ones, and some coverage gaps.

1. The playbook engine's own DAG dispatch inherits the turn's generated worker charter (CONFIRMED -- please answer before merge)

_preflight is shared by every SubAgentDagTool instance, including the private, unregistered one the playbook engine dispatches through (loop/wiring.py:1307-1324). load_playbook reaches it in-turn:

tools/load_playbook.py:179 -> playbook/runtime.py:432 -> playbook/executor.py:397 -> _dispatch (:511) -> self._dag_tool.execute(...) (:564), inside the turn's delegate_scope (loop/main.py:923-933).

So the new block at dag_tool.py:1507-1525 resolves the conversation's worker table for a graph a playbook wrote, not the model. Generated labels default to the agent name (the emit schema says "Give one only when the same agent appears more than once; otherwise omit it", playbook/agent_generator.py:145-151, applied at :320), so a playbook step naming that agent hits a label. Two silent effects: the step's task is prefixed with a brief written for the conversation (dag_tool.py:224-226), and dispatch_charter(payload) narrows the worker's tools, rules and deadline inside the worker process (backends/raven_loop.py:234,246) whenever the generated row declared tools / checks / timeoutSeconds (playbook/agent_generator.py:248-276). The direction is narrowing, never widening (tools/registry.py:428-448), so this is correctness, not privilege.

Options: give the private playbook instance a flag that ignores the turn table; pass the table explicitly rather than reading a turn-scoped ContextVar in a seam two consumers share; or bind delegate_scope(None) around the playbook's own dispatch.

2. Lower priority

  • _WorkerBackend.run(..., **kwargs) (dag_tool.py:224) makes optional_keyword always answer yes, so authored_task is handed to a backend that never declared it (dag_runner.py:1671, backends/base.py:157-175) -> TypeError. All five in-tree backends declare it (raven_loop.py:216, openai_api.py:189, cli_agent.py:529, routing.py:312, acp_client/acp_agent.py:1123) and RoutingBackend re-probes (routing.py:338), so this is latent; _DispatchBackend set the precedent. Declaring authored_task: str | None = None on the wrapper closes it.
  • __getattr__ recursion on copy / deepcopy / pickle (dag_tool.py:221-222, same shape at :192-193). self.__dict__.get("backend") fixes it. Nothing in-tree copies a node backend today.
  • _convert_tool_choice (providers/openai_codex_provider.py:46-55) is byte-for-byte the pre-existing copy at providers/openai_responses_provider.py:29-37, and that module already imports its siblings from the codex module. Importing it there (or giving all of them one home) is what keeps the two Responses transports from drifting.
  • CONTEXT.md:129-131: the Worker Table definition still says the label reaches the model as spawn's enum only. This change also puts it on run_subagent_dag and resolve_dag_node, resolved at preflight, so the definition no longer verifies against the code (AGENTS.md section 6).

3. Coverage

  • The new DAG test stops at _preflight and calls the frozen backend directly; nothing runs the graph (_run / run_dag). Reverting dag_tool.py:1822 to self._resolve_node would break no test, so the line that consumes the freeze is unguarded. Running one worker-labeled node end to end (recording backend; assert charter + prompt and outbound_charter() == payload) would catch it.
  • The codex tests cover the helper, not the call site: reverting openai_codex_provider.py:96 to tool_choice or "auto" would break no test. _capture_body already exists in that file, so the body assertion is one line away.
  • validate_capabilities skips names absent from the capability map (dag_capabilities.py:39), so nothing covers a labeled node whose backing agent cannot do what the node asks.
  • The new test's comment ("a background graph starts after this turn scope has gone away") does not match asyncio.create_task context copying, which keeps the table readable after the scope closes.
  • No integration test exercises run_subagent_dag at all, and tests/integration/test_subagent_charter_e2e.py covers the spawn lane only, so the DAG lane has no end-to-end charter assertion.

4. Process

  • The title is fix(agent): ..., but the only commit carrying new content is feat(playbook): route DAG nodes through generated harness. The squash commit on main takes the PR title, so this lands as a fix and semantic-release would only patch.
  • The description describes the participant-roster work that is already on main via refactor(agent): ask a role once with the turn's whole roster #532; the effective diff is the five files above, and the verification list covers files outside it.
  • The branch takes main in through merge commits (e74c12b7, then f0ca4db7) rather than the rebase flow in AGENTS.md section 3.5. It is up to date with main now and the merge is clean (GitHub reports BLOCKED, not DIRTY), so this is a process call rather than a conflict.
  • The three content commits are authored by yaopengfei@shanda.com, which is not linked to a GitHub account (author_login null, unverified). With require_extra_approval_for_unattributed_changes on the branch ruleset, this PR needs two approvals, not one.
  • No commit carries a Co-authored-by trailer. Section 3.3 asks for one only when Claude wrote the code, so this is a question rather than a finding.

Merge gate today: reviewDecision=REVIEW_REQUIRED, mergeStateStatus=BLOCKED, 0 approvals (both existing reviews are COMMENTED), 0 unresolved threads. dismiss_stale_reviews_on_push is on, so approvals have to come after the last push.

Checked and sound, so the list above is the whole of it: the label-resolution contract matches spawn's (unknown names pass through, the roster check is the refusal point); resolution happens before validate_capabilities, _registry.get and instance minting, so capability gates and every recorded identity use the real agent; workers is keyed by node id, which validate_and_order keeps unique; to_schema() is the declared-dynamism idiom (registry.py:105-106), not dead code; a charter can only narrow; replans go through _preflight too (dag_tool.py:1344) and carry the frozen backends; enabled defaults to True, so the new master-switch guard changes nothing for existing installs; the render is deterministic, so it does not churn the prompt prefix within a turn; the added lines are ASCII English and the new comments explain why, not what.

@gloryfromca

Copy link
Copy Markdown
Member

Blocking: stored playbook DAGs must not inherit a turn-generated worker charter.

I independently confirmed the substantive path in comment 5750557822. Using the loop-built private playbook DAG tool under a generated DelegateTable whose default label was Raven, _preflight returned _WorkerBackend; invoking that backend changed the stored task to TURN CHARTER\n\nstored task and exposed the generated payload {"tools": ["read_file"]} through outbound_charter(). Thus an ordinary load_playbook DAG can silently receive conversation-specific instructions and capability narrowing whenever agentHarness: generate emits the same agent-name label.

This changes my standing stance from clean to blocking. The required outcome is that the private playbook executor dispatches its authored graph without consulting the turn-generated worker table; the implementation choice remains with the author.

Verification: uv run pytest tests/test_playbook_executor.py tests/test_agent_playbook_delegate.py -q passed 94 tests, demonstrating that the existing suite remains green despite the reproduced cross-path contamination.

@gloryfromca gloryfromca left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking: stored playbook DAGs still inherit the turn-generated worker charter.

This revision only merges the latest main change for on-call campaign billing. I compared the effective PR diff and commit range with f0ca4db7d0f3: all authored Harness/DAG/provider changes are identical, and the private playbook SubAgentDagTool still reaches the shared _preflight path that consults current_delegate(). Therefore the blocker confirmed in comments 5750557822 and 5750576974 remains unchanged on this head.

For this revision I checked the delta, affected call path, history/range-diff, repository and architecture constraints, backward-compatible paths, and tests for weakening. uv run pytest tests/test_playbook_executor.py tests/test_agent_playbook_delegate.py -q passed 94 tests; those tests still do not exercise the cross-path charter contamination.

@ypflll
ypflll force-pushed the refactor/participant_full_roster branch from 35b9f17 to 3086ced Compare September 21, 2026 03:27
@ypflll ypflll changed the title fix(agent): preserve harness context across hooks and DAG delegation feat(playbook): route DAG nodes through generated harness Sep 21, 2026
@ypflll

ypflll commented Sep 21, 2026

Copy link
Copy Markdown
Contributor Author

@LivXue @gloryfromca The blocking stored-Playbook contamination path is fixed on 3086cede.

The public DAG still reads the turn Worker Table, while the private Playbook DAG is now constructed with an explicit empty Worker Table source. The regression test runs a stored Playbook through PlaybookRuntime.load() and the real blocking DAG path under a colliding Raven worker label, then verifies the stored agent and prompt are preserved and no turn charter payload reaches the backend.

The lower-priority findings are also addressed: legacy authored_task forwarding, copy-safe wrappers, shared Responses tool-choice conversion, current Worker Table documentation, resolved-agent capability validation, Codex request-body coverage, and the inaccurate ContextVar comment.

Post-rebase verification: 613 relevant tests passed; repository-wide lint and changed-source type checks passed. The branch is rebased onto current main.

@gloryfromca gloryfromca left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blockers; suggestions only, and they are marked inline.

The previous blocker is fixed: the stored Playbook's private DAG tool now injects an isolated worker-table source, and the collision regression verifies that neither the turn-only charter nor its payload reaches the stored node. This lifts my blocking stance.

I left one nonblocking compatibility follow-up inline for the production worker/MCP-adapter wrapper order. It is reproducible, but it requires the generated harness, DAG MCP adaptation, and a pre-authored_task third-party backend together, so it does not meet the late-round ordinary-reachability bar.

I covered AGENTS.md, CLAUDE.md, CONTEXT-MAP.md/CONTEXT.md, the effective diff, callers and construction paths, history/range-diff, backward compatibility, test weakening, and the Harness/Worker Table architecture constraints. git diff --check was clean. Focused runs passed 39 playbook-delegation tests and 85 executor/provider tests. The broader DAG/provider/third-party run reported 801 passed and 3 failed; all three failures are in untouched DAG-memory tests and report the unavailable everos-memory plugin in this environment.

Comment thread raven/agent/subagent/dag_tool.py

@gloryfromca gloryfromca left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blockers; this can merge as far as I am concerned.

The compatibility fix is correct: _DispatchBackend now consumes authored_task, checks the wrapped backend before forwarding it, and the regression uses the production wrapper order. The former direct reproduction now succeeds.

For this revision I covered the delta and effective diff, the wrapper callers and construction order, history/range-diff, backward compatibility, test weakening, and the previously checked repository and architecture constraints. git diff --check was clean. The focused playbook/provider run passed 66 tests. The broader affected run reported 801 passed and the same 3 failures in untouched DAG-memory tests caused by the unavailable everos-memory plugin in this environment. My previously opened thread is resolved.

@ypflll

ypflll commented Sep 21, 2026

Copy link
Copy Markdown
Contributor Author

@LivXue Final head bfb94335 is ready for the required human approval: all GitHub checks are green, the blocker and follow-up thread are resolved, and the reviewer bot reports no blockers. Please submit a fresh APPROVE review for this head when available; the previous review gate was reset by the fix push.

@gloryfromca gloryfromca left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blockers; this can merge as far as I am concerned.

This is a merge-only revision. The range-diff keeps all three authored commits unchanged, the combined merge diff contains no conflict-resolution changes, and the effective PR diff remains the same seven files reviewed at bfb94335.

For this round I checked the head delta, effective diff, merge/history shape, preservation of the previously reviewed callers and backward-compatibility fix, test changes for weakening, repository diff hygiene, and the standing Harness/Worker Table architecture constraints. git diff --check was clean, and uv run pytest tests/test_agent_playbook_delegate.py tests/test_openai_codex_provider.py -q -n 0 passed all 66 tests. My only prior thread remains resolved.

Comment thread raven/agent/subagent/dag_tool.py Outdated
@LivXue

LivXue commented Sep 21, 2026

Copy link
Copy Markdown
Member

Blocking: 1 finding needs correction before this revision can merge; see the inline note.

Scope: I reviewed only the raven/agent/** portion of this PR - 2 of 7 changed files (raven/agent/subagent/dag_tool.py, raven/agent/loop/wiring.py). The remaining 5 were read as context but are not covered by this verdict.

This is a re-review. I last reviewed head f0ca4db7 and carried seven findings. All seven are closed, confirmed one at a time below.

I ran this review at bfb94335. The head has since moved to b9ad5bb4, which only merges main: the effective diff against the merge base is byte-identical between the two, so nothing below was re-run and nothing below needs to be.

Closed since the last round

  1. Stored playbook DAGs inheriting the turn worker charter (the standing blocker, also held by gloryfromca). Fixed. The private playbook tool is built with worker_table_for=lambda: None (wiring.py:1330-1333), and self._worker_table_for() replaces current_delegate() at all three read sites. Reproduced clean: under a colliding Raven label the private instance returns the bare node backend, delivers the stored task verbatim, and outbound_charter() is None, while the public instance on the same table still wraps, prefixes and carries the payload.
  2. _WorkerBackend.run inverting optional_keyword for a backend that never declared authored_task. Fixed in both wrapper orders. Reproduced: _WorkerBackend(_DispatchBackend(legacy, drop_mcps=True)) and the inverse both deliver BRIEF\n\ntask without forwarding the keyword, while a backend that does declare it still receives it.
  3. __getattr__ recursion under copy, deepcopy and pickle. Fixed, and the fix reached the pre-existing twin: both _WorkerBackend and _DispatchBackend round-trip. Worth recording for the history - at the merge base _DispatchBackend already raised RecursionError on all three protocols and already raised TypeError on the legacy-forwarding path, so on both counts this PR repairs pre-existing defects rather than introducing new ones.
  4. _convert_tool_choice duplicated between the two Responses transports. Fixed. The responses module now imports it alongside the three siblings it already took from the codex module, and one definition remains in the tree.
  5. The line that consumes the frozen backends was unguarded. Closed. Reverting dag_tool.py:1842 to resolve=self._resolve_node now fails test_stored_playbook_dag_ignores_the_turn_worker_table (1 failed, 135 passed); the same mutation was green at the previous head.
  6. CONTEXT.md's Worker Table definition no longer matching the code. Fixed. The definition now names all three tools that carry the label and states the stored-playbook isolation.
  7. The title describing work already on main. Fixed by the retitle and the rebase, which dropped the two participant commits from the range.

Confirmed finding

  • Blocker, dag_tool.py:1020, for a defect at the untouched line 299. _node_schema swaps the subagent enum for labels but leaves the field description saying "from the roster". A model that follows the field text picks a roster name, _preflight leaves it unresolved, and the node dispatches with neither its brief nor its charter. spawn avoids this by rebuilding the whole property per table state (spawn_tool.py:212-228). Details and the reproduction are in the inline note.

Out of scope, disclosed rather than filed

raven/cli/playbook_commands.py:417 is a third SubAgentDagTool construction - the raven playbook run executor's own private instance - and it does not pass worker_table_for. It is not reachable today: delegate_scope is entered at exactly one place in the tree (raven/agent/loop/main.py:927), so no table can be bound in a CLI process. I raise it because CONTEXT.md now states the isolation as a contract of "a stored Playbook's private DAG tool", and this site satisfies that by environment rather than by construction.

Verification

On bfb94335 unless stated otherwise - see the note above on why that is this head's diff.

  • Reproductions ran against a worktree at the head with that tree first on sys.path; the base comparisons ran the same way against the merge base db7862ae2.
  • Rendered the model-visible tool definitions at both shas. With no table bound, run_subagent_dag is byte-identical base to head in name, description and parameters. With a table bound, the only parameters difference is nodes.items.properties.subagent.enum, and the base does not react to a table at all. schema_dynamic for the tool flips from False to True, so it is served live rather than from the admission snapshot.
  • pytest: 221 passed on the focused playbook, provider and DAG-control set; 636 passed on the wider DAG, playbook and provider set; 273 passed and 8 skipped on the six provider files that reach openai_responses_provider.
  • lint-imports: 10 contracts kept, 0 broken, including cargo not importing the loop shell.
  • ruff check on all six changed files: passed.
  • Added lines carry no non-ASCII characters.

Checked and deliberately not reported

  • The DAG orchestration skill is untouched, and none of the watched dispatch symbols appears in the diff.
  • No guard or comment was deleted. All 25 removed lines are replaced expressions or the relocated _convert_tool_choice.
  • A prompt-mode playbook cannot emit a label: its compose schema comes from the pydantic model (playbook/prompt.py:373) and its agent list from agent_profiles_from_registry, which is keyed by roster name.
  • The third delegating __getattr__ in the tree (backends/routing.py:167) was never vulnerable to the copy recursion: it refuses any attribute starting with an underscore, which is every hook that copy and pickle look up.
  • Closed finding 5 is held by an incidental assertion - the mutation is caught by a resolve-call count rather than by a charter assertion, because the public-path charter test still stops at _preflight.
  • There is no tests/test_openai_responses_provider.py; the dedup in closed finding 4 is covered only by the six files that import the module.
  • Not a code finding, for the merge gate: the three commits are still unattributed (author.login null, unverified), so require_extra_approval_for_unattributed_changes applies and this PR needs two approvals. It has none - all nine existing reviews are COMMENTED.

@gloryfromca gloryfromca left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking: the outstanding schema-label thread needs its author to confirm the fix.

The code change itself addresses the reported defect: the Worker Table branch now replaces both the enum and its model-facing description, matching the established spawn contract, and the live schema reproduction shows the corrected instruction. I found no new code issue.

For this revision I checked the delta and effective diff, schema consumers (run_subagent_dag and resolve_dag_node), the spawn precedent, history/range-diff, backward compatibility, test weakening, repository diff hygiene, and the Worker Table architecture contract. git diff --check was clean, and the focused playbook/provider run passed all 66 tests.

LivXue's blocking thread remains open. Because it is not my finding, I have left resolution and any severity change to its author or a maintainer.

@ypflll

ypflll commented Sep 21, 2026

Copy link
Copy Markdown
Contributor Author

@LivXue The schema-label blocker is fixed on the current head 4dffdf63. The DAG subagent property now describes Worker Table labels whenever its enum contains labels, and the regression covers the live schema. Local verification passed 297 focused tests plus Ruff and ty; all GitHub checks are green. Please re-review and resolve discussion 4059675252 if satisfied.

@gloryfromca gloryfromca left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking: the outstanding schema-label thread still needs its author to confirm the fix.

This is a merge-only revision. The range-diff preserves all four authored commits, the combined merge diff contains no conflict-resolution changes, and the effective PR diff is unchanged from 4dffdf63, where the schema fix was verified.

For this round I checked the head delta, effective diff, merge/history shape, preservation of the schema fix and prior compatibility paths, test weakening, diff hygiene, and the standing Worker Table architecture contract. git diff --check was clean, and the focused playbook/provider run passed all 66 tests.

LivXue's blocking thread remains open with no confirmation on the fixed code. I have not resolved or downgraded someone else's finding.

@gloryfromca gloryfromca left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking: the outstanding schema-label thread still needs its author to confirm the fix.

This is a merge-only revision. The range-diff preserves all four authored commits and the effective seven-file PR diff. The merge has one manual resolution in CONTEXT.md; I checked it and it correctly retains the Worker Table contract alongside current main. No product-code conflict resolution altered the reviewed fix.

For this round I checked the head delta, effective and combined diffs, history/range-diff, the schema and compatibility paths, test weakening, repository rules/diff hygiene, and the Worker Table architecture terms. git diff --check was clean. Because current main changed subagent routing and registry code, I included that suite: 121 focused playbook/provider/routing tests passed.

LivXue's blocking thread remains open with no confirmation on the fixed code. I have not resolved or downgraded someone else's finding.

@gloryfromca gloryfromca left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking: the outstanding schema-label thread still needs its author to confirm the fix.

This is a merge-only revision. After refreshing github/main, the range-diff preserves all four authored commits and the effective PR diff remains the same seven files. The merged shutdown fix overlaps dag_tool.py outside the Worker Table/schema path and required no conflict resolution, so the verified schema fix remains intact.

For this round I checked the head and effective diffs, merge/history shape, the overlapping DAG lifecycle change, preservation of schema and compatibility paths, test weakening, diff hygiene, and the Worker Table architecture contract. git diff --check was clean. The expanded playbook/provider/DAG-runner/manager run reported 487 passed and the same 3 environment failures in DAG-memory tests caused by the unavailable everos-memory plugin.

LivXue's blocking thread remains open with no confirmation on the fixed code. I have not resolved or downgraded someone else's finding.

@LivXue LivXue left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving at bcc2d558.

Scope: I reviewed only the raven/agent/** portion of this PR - 2 of 7 changed files
(raven/agent/subagent/dag_tool.py, raven/agent/loop/wiring.py). The remaining 5 were read
as context but are not covered by this verdict.

This is my third round. Round 1 at f0ca4db7 carried seven findings; round 2, run at
bfb94335 and posted at b9ad5bb4, closed all seven and filed one Blocker. That Blocker is
now closed.

Why this round re-ran rather than inherited its predecessor: the head has taken three merges
of main since the fix commit 4dffdf63, and dag_tool.py differs from the version the fix
was verified on (+20 -6, main's TaskAdopter refusal change), with one manual conflict
resolution in CONTEXT.md. Everything below was re-derived at bcc2d558.

Findings, all closed at this head:

  • The schema-label Blocker: fixed and guarded by a regression test. The reproduction and the
    detail are in that thread.
  • Legacy authored_task forwarding: fixed in both wrapper orders, plus the case the earlier
    rounds did not show - a backend that does declare authored_task still receives it, so the
    suppression did not overshoot.
  • __getattr__ recursion under copy, deepcopy and pickle: all six round-trips clean.
  • _convert_tool_choice dedup and the CONTEXT.md Worker Table definition: both landed.

Verification on bcc2d558:

  • Reproductions ran against a tree extracted at this head, with that tree first on sys.path.
  • Rendered the live run_subagent_dag and resolve_dag_node node schemas, with and without a
    bound Worker Table.
  • Mutation check: deleting the description branch fails
    test_the_workers_replace_the_dag_roster_too (1 failed, 38 passed).
  • pytest: 66 passed on test_agent_playbook_delegate.py and test_openai_codex_provider.py;
    567 passed across the DAG core, runner, control-tools, MCP-scope and playbook-executor set.
  • CI at this head: 20 pass, 2 skipping, 0 fail.

Carried forward from round 2, unchanged and disclosed rather than filed:
raven/cli/playbook_commands.py:417 is a third SubAgentDagTool construction that does not
pass worker_table_for. It is unreachable today, since delegate_scope is entered at exactly
one place in the tree, but CONTEXT.md now states the isolation as a contract of this class of
tool, and that site satisfies it by environment rather than by construction.

Not a code finding, for the merge gate: four of the eight commits are still unattributed
(author.login null, unverified), so require_extra_approval_for_unattributed_changes applies
and this PR needs a second approval beyond this one.

@ypflll
ypflll merged commit 87f3928 into main Sep 21, 2026
25 checks passed
@ypflll
ypflll deleted the refactor/participant_full_roster branch September 21, 2026 10:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants