Skip to content

fix(subagents): preserve role routing and assign discovery early - #130

Open
thisisjun786 wants to merge 12 commits into
lidge-jun:devfrom
thisisjun786:codex/explorer-routing-fix
Open

fix(subagents): preserve role routing and assign discovery early#130
thisisjun786 wants to merge 12 commits into
lidge-jun:devfrom
thisisjun786:codex/explorer-routing-fix

Conversation

@thisisjun786

@thisisjun786 thisisjun786 commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Explorer requests could inherit the parent model when callers used native items, while review-related words could override an explicitly selected explorer role. This change preserves explicit role selection, configured model/effort, attachments and both supported input forms. It also makes discovery ownership an early decision: delegate an independent question before reading that source, revisit the split as scope grows, and keep narrow lookups and explicit no-delegation local. SessionStart spells out the actual dispatch report schema.

The reviewed payload paths now deduplicate skill bodies across all text items and enforce the complete projected-text limit, preserve item whitespace, and keep ignored-config warnings/guards stable on reapplication. Managed dispatch markers are accepted only in the first producer header or behind exact hook-owned prefixes; quoted logs cannot consume another spawn's claim. Both reviewer recovery producers preserve reviewer settings on native, legacy explorer, and fieldless hosts.

Validation:

  • Current PR head daa3cb6b: focused source receipt 266 passed, 0 failed, clean source identity. Final implementation 26f0bc25: full suite 3,032 tests, 2,960 passed, 0 failed, 72 skipped. The following commit only archives evidence and updates README counts.
  • Added 11 hook regressions and 2 runtime producer-to-resolver tests with demonstrated failures before their repairs. Independent final review passed all five findings after two additional boundary corrections.
  • Build compiled 179 files; gate, inventory and Linux smoke passed. Installed compiled tests passed 13/13; the installed hook CLI preserved items/attachments/whitespace, injected configured model/effort, deduplicated bodies and returned a no-op on reapplication. All 13 audited installed hashes match the preserved local integration; doctor passed with 29 trusted hook hashes.
  • Earlier fresh native CLI Astra and Sol broad cases each dispatched one configured explorer before source loading and used its evidence. Narrow and explicit no-delegation cases used zero children. Those observations retain their original revisions and limitations; this payload repair did not rerun an expensive model benchmark.

Evidence: payload repair and reproducible checks, earlier discovery behavior study.

Limits: delegation remains agent-followed guidance. The earlier CLI baseline/candidate versions differed (0.153.4/0.154.0), one Sol probe timed out, and a final attempt-ID error was rejected and recovered. That small sample establishes neither universal behavior nor net cost savings. Local account-catalog changes are preserved; private logs and account data remain outside Git. No provider defaults, retry policy, upstream merge or deployment is changed.

Current PR head daa3cb6b: all 13 hosted checks passed, including Linux/macOS/Windows suites, the aggregate CI check and packed-install lifecycle. CI run, packed-install run. The preserved local integration at 7cdeae00 separately passed its 3,033-test suite (2,961 passed, 0 failed, 72 skipped), including its additional local catalog regression.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 10, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-10T18:31:58.341530Z daa3cb6 New commits
🔒 Security Review Completed 2026-09-10T11:47:10.548955Z 1587ae6 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1587ae6bda

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/codexclaw/components/subagent-config/src/spawn-attach-hook.ts Outdated
Comment thread plugins/codexclaw/components/subagent-config/src/spawn-attach-hook.ts Outdated
@thisisjun786 thisisjun786 changed the title fix(subagents): preserve explorer routing across native input forms fix(subagents): preserve explorer routing and assign discovery early Sep 10, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0b811d3f4a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/codexclaw/components/subagent-config/src/spawn-attach-hook.ts Outdated
@thisisjun786

Copy link
Copy Markdown
Contributor Author

Follow-up inspection of 0b811d3f4afbafc5948b2c0868757b725db0a5d1: the intended routing and discovery-guidance changes are present, but five P2 findings remain reproducible and should be repaired before merge. All five existing review threads are unresolved and current.

This pass checked the 1587ae6b..0b811d3f follow-up diff, its generated dispatch-guidance export, the existing hook findings, and the legacy reviewer producers they affect.

The change addresses two separate problems:

  • A requested explorer could receive the wrong configuration. The old hook returned early for native items input, skipping model/effort injection. It also let words such as review or 검증 override an explicit explorer, including negative instructions. The hook now handles both native input forms and gives explicit explorer selection precedence, while retaining deliberate CXC-ROLE headers for legacy logical roles.
  • Discovery was often kept in main. The earlier guidance only asked main to consider an explorer. The follow-up requires deciding ownership before broad reads, delegates an independently answerable question when main has separate useful work, and revisits that split after scope growth or truncation. The child returns a bounded answer with source anchors; main verifies relevant spans. Narrow lookups and explicit no-delegation remain local. SessionStart also gives the actual action: "report", outcome: "created" | "complete" | "failed" fields. Cost calculation is conditional on making a comparison, not a prerequisite for ordinary delegation.

I checked the automated findings with isolated synthetic fixtures against the current source. These checks invoke the local hook/resolver and fixture dispatch store; they do not create native agents or call a provider.

Existing finding Current-head reproduction Repair needed
P2: aggregate inline limit, spawn-attach-hook.ts:821 Twenty small $cxc-dev text items produce 20 copies of the body: a 715-byte tool input becomes 542,578 projected text characters, exceeding the 262,144-character bound. Deduplicate skills across the request and apply the atomic limit to the combined text before attaching bodies, preserving item boundaries.
P2: legacy reviewer producers, attest.ts:188 and review-round-cli.ts:200 Both producers still tell callers to use explorer transport without the deliberate reviewer header. Executing the role resolver yields explorer; adding CXC-ROLE: reviewer before TASK: yields reviewer. Align those recovery instructions with the supported native role and legacy header contract. This is source/resolver proof, not a fresh legacy-host agent run.
P2: preserve item whitespace, spawn-attach-hook.ts:819 A separate text item beginning with four-space-indented YAML loses that indentation and trailing blank lines despite containing no control marker. Remove control tokens without trimming or collapsing the contents of each supplied item.
P2: ignored-config idempotence, spawn-attach-hook.ts:885 and :903 With an untrusted Git-tracked project config, applying the hook twice increases both warning and guard counts from one to two. Recognize the existing warning/guard envelope and emit each once.
P2: quoted dispatch marker, spawn-attach-hook.ts:801 and :806 A later text item quoting a valid claimed marker from the same session causes an unrelated synthetic call to consume that claim. The intended call is then denied with attempt already issued to another native call. Recognize dispatch authority only in the producer header, while preserving valid hook reapplication and single-use claims.

The current head has 13 successful hosted checks. Its existing focused-test receipt still matches this exact SHA (51 passed, 0 failed); the dispatch-guidance source and generated export also match. Those checks do not cover the five cases above.

The published behavior evidence remains a small native-CLI case study: repaired Astra and Sol each used one configured explorer and completed, while narrow/no-delegation cases used none. The CLI-version change, earlier incomplete Sol probes, and recovered attempt-ID error remain disclosed. This establishes observed behavior, not universal dispatch behavior or net cost savings.

blocking_issues: the five verified P2 cases above. This comment records their confirmation; it does not mark their review threads resolved.

Verdict: repairs needed before merge.

@thisisjun786 thisisjun786 changed the title fix(subagents): preserve explorer routing and assign discovery early fix(subagents): preserve role routing and assign discovery early Sep 10, 2026
@thisisjun786

Copy link
Copy Markdown
Contributor Author

Follow-up to the reproduced five findings: all five are fixed and their review threads are resolved at daa3cb6b.

  • Skill bodies are deduplicated and capped across the full items text, including hook prefixes.
  • Item whitespace and attachments survive cleanup; ignored-config packets remain stable on repeated application.
  • Quoted dispatch markers cannot issue another call's claim. Exact legitimate wrappers, same-tool reapplication and existing denial cases are covered.
  • Reviewer recovery advice covers native reviewer, legacy explorer and hosts without a role field. Runtime producer-to-resolver tests verify the configured reviewer model, effort and prompt with neutral task text.

Evidence: red-green regressions, final independent review PASS, 266 current-head focused checks, 2,960 full-suite passes / 0 failures / 72 skips, and 13/13 hosted checks. The preserved local integration separately passed 2,961 / 0 / 72. The installed compiled code passed all 13 new tests; the actual installed hook CLI passed the payload smoke, with 13 matching source/artifact hashes and 29 trusted hook hashes.

Repair record and reproducible checks. These checks establish routing/payload behavior; they do not claim universal delegation frequency or net cost savings. The earlier native behavior study retains its original scope and limitations.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: daa3cb6bb5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if (/^\[CXC-DISPATCH:/m.test(dispatchScan)) {
let dispatchSource = "";
let dispatchError: unknown;
const sources = dispatchSources(validItems ? textItems[0]?.text ?? "" : message, cwd);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Locate managed headers in the actual task item

When a managed V1 items request is produced by buildSpawnItems with cwd and a task containing an existing path, spawn-wrapper.ts:256-261 inserts a path-hint text item before the trailing task item where the dispatch marker is prepended. Inspecting only textItems[0] therefore misses the valid marker: the hook uses the primary configured model instead of the claimed candidate, adds the unmanaged warning, and leaves spawnIssued false even though the child is launched. Identify the producer-controlled task item rather than assuming the first text item is the dispatch header.

Useful? React with 👍 / 👎.

// and before the allow/no-op below so a denial reaches the caller unchanged.
const gateCheck = checkFinalGatePrereqs(
evidenceExemptMessage,
updatedItems ? updatedItems.filter(item => item.type === "text").map(item => item.text).join("\n\n") : evidenceExemptMessage,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Restrict final-gate authority to the task packet

In a goalplan-bound session whose final-gate receipts are not yet present, any supplemental text item containing the literal [CXC-FINAL-GATE]—for example, a quoted log or this hook's source—now causes an unrelated items-form spawn to be denied because every text item is concatenated and checkFinalGatePrereqs uses a raw includes check. Non-text attachment metadata is deliberately excluded from marker authority, but quoted text needs the same protection; inspect only the producer-controlled task packet while still supporting the trailing task item emitted by buildSpawnItems.

Useful? React with 👍 / 👎.

Comment on lines +858 to +861
const mappedItems = validItems ? itemInput.map(item => {
if (item.type !== "text") return item;
const controlled = stripControlMarkers(item.text, true);
const normalized = skillsDir ? normalizeSkillMentions(controlled, skillsDir) : controlled;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve minted recursion grants on hook reapplication

When an items-form root spawn requests recursion and the host reapplies the hook to its rewritten input, this mapping strips the hook-minted [CXC-SUBSPAWN-GRANT:…] from the coordinator instruction. Because the public request token was already removed, the second pass also selects the ordinary leaf guard, leaving two contradictory guards and no usable capability, so the authorized child cannot perform its one permitted spawn. Recognize and preserve the exact hook-owned coordinator/grant prefix on root reapplication while still consuming the grant when a child actually presents it.

Useful? React with 👍 / 👎.

? (firstText < 0 ? "" : mappedItems[firstText].text as string)
: stripControlMarkers(message);
const normalizedMessage = !mappedItems && skillsDir ? normalizeSkillMentions(controlledMessage, skillsDir) : controlledMessage;
const role = managed?.role ?? inferRole(toolInput.agent_type, validItems ? dispatchScan : normalizedMessage);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Derive role headers from the task item only

For structured items where supporting text precedes the trailing task item, any quoted CXC-ROLE: line in that supporting text is included in dispatchScan and wins inferRole's first-marker match before the real task header. This can route an explicitly explorer-typed request to the reviewer configuration, including the wrong model, effort, and prompt, whenever a source excerpt contains such a marker before the task's TASK: line. Pass only the producer-controlled task header to role inference rather than concatenating every text item.

Useful? React with 👍 / 👎.

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.

1 participant