Skip to content

Make the parent re-evaluate its candidates instead of being told to - #87

Merged
thisisjun786 merged 13 commits into
devfrom
codex/crw-133-proactive-run
Sep 20, 2026
Merged

thisisjun786 merged 13 commits into
devfrom
codex/crw-133-proactive-run

Conversation

@thisisjun786

@thisisjun786 thisisjun786 commented Sep 20, 2026

Copy link
Copy Markdown
Owner

Problem

The scan that fills empty capacity with ready successors already existed (Establish the project baseline), but two things were missing, and together they meant a parent waited to be told.

Nothing said when the scan runs. The trigger list named initial dispatch, a completion, a blocker and an integration, and omitted resume and recovery — and nothing made the scan a duty before the turn ends, so a parent could end on a final answer describing what it would dispatch.

Nothing said how a parent learns a child stopped. assignment-find and the verification reads answer about ready_for_review and nothing else, so a child that recorded blocked_needs_input was invisible and a coordinator reading only those concluded nothing was wrong. The reads that answer this landed very recently (#71, #73, #86) and no skill instruction named any of them.

And Record a concrete dependency, conflict, ownership, or capacity reason for deferring an otherwise ready issue let one sentence cover a blocked prerequisite, an owner nobody could prove, and a capacity nobody measured. Those recover differently, so a later pass could not tell which condition to re-read.

What changed

Inline in SKILL.md, because it has to be loaded every turn: the forcing-event set now includes resume and recovery; the scan is a duty before the turn ends, or the reason it could not be read is recorded; an issue that already has a responsible child is not a candidate and doctor --issue answers that from one non-constructing read before anything is created; stopped children are enumerated with dispositions-show instead of their silence being read as progress; and the deferral reason comes from a closed set.

references/reevaluation.md (new, table-only) carries what needs a table rather than a sentence: the read behind each forcing event, what the stopped-children reader does and does not answer, the closed decision set with the condition that clears each value and the row it rests on, and the per-candidate record with what each absence means.

references/task-packet.md gains the coordination-record field a checkpoint reads. The record list was closed and had no entry for candidates, decisions or holds, so that state was unobservable.

Before / after

A child records blocked_needs_input and the parent is mid-run.

  • Before: the reviewable reads say nothing, the parent sees a quiet project, and the blocked child is found when a person mentions it.
  • After: the pass enumerates stopped children, the blocked one is a forcing event, and the parent either dispatches the independent work that is still ready or records why each candidate is held.

Design constraints kept

No scheduler, no new store, no cursor, no second opinion about anything the relay already decides. Words that already have owners stay there: capacity bounds and unmeasured in start-policy.md, reader vocabulary in relay.md (which explicitly reserves it), the turn-ending prohibition in OPS-8.1, record location in task-packet.md.

The closed set has no escalation value, so a review-round count has nowhere to land — the parent rules on criteria and correction scope and returns the work to the same child.

Ownership uses one read where one read suffices: doctor --issue is non-constructing and deliberately narrow (first live relationship, silent about a second). assignment-find --issue reports ambiguity but constructs a store, so it is ordered second and only after storeAgreement: same.

Validation

python3 scripts/ci/plugin.py exit 0; python3 scripts/ci/validate.py exit 0 (Validated 9 skills, local link paths and Python syntax); quick_validate.py plugins/crw/skills/crw-run exit 0; git diff --check clean. Independent adversarial review was run against the committed diff and the landed payloads.

No gate interprets the meaning of instruction prose; that is human review, and this PR does not claim otherwise.

Scope and what this does not establish

This lands source. It does not install anything and it is not evidence of live behaviour. The issue's criterion requiring an installed relay and observed multi-issue runs is a separate step a merge does not produce.

Commits ee5d802 and 8e4917d on this branch are the earlier Phase A wording fixes for the same issue, already reviewed.

Four readers named for the remaining forcing events (merge-turn-show, linkage-*, region-*, capacity-show) have no skill-level usage documentation yet; the file says so rather than implying coverage. Documenting them is a follow-up.


Devin Review


Review rounds on this PR

Five independent review rounds on the built diff, ending PASS, plus two defects found by Devin on pushed heads and fixed:

Head Finding Fix
2601417 The reference restated relay.md's own vocabulary after saying it would not, and the copies had drifted; the forcing-event table disagreed with SKILL.md and listed a mutating command as a read; two payload claims were wrong; supersession does not clear a contested disposition; the set could not record a criteria contradiction fb9313d
fb9313d defer:scope_ambiguous was unreachable: the project-scope reading only exists when an assignment does, which holds: true already ends 5d63f55, e617b08
25bf819 Direct runs deferred every candidate. With no relay store doctor --issue returns holds: null, so every ready issue became defer:ownership_unverified and a direct run would dispatch nothing 25bf819 scopes both reads to the determined execution mode
77824b4 That fix overcorrected: excluding direct mode removed the only ownership hold, so an unreadable coordination record had no safe decision 77824b4 separates relay absence (not a hold) from a failed read (a hold in either mode)

Both Devin threads are resolved by Devin itself (4057944064, 4057998554).

65e07ae adds the last criterion this phase owed: a review-round count is not a reason to send an approved correction upward. It had been resting on the closed decision set having no escalation value, which governs candidate holds rather than corrections, so it never reached the section that actually returns one.


Update (6eb36b7): the four readers the pass names — merge-turn-show, region-show, capacity-show, linkage-outstanding — now have a usage contract in relay.md, taken from their handlers and parsers. This was the one finding both the independent reviewer and Devin raised that I had deferred as a follow-up; it is closed here instead, so no follow-up issue is needed for it. reevaluation.md no longer says they are undocumented.

Head 6eb36b7 is green on run 35537572242: dev-gate pass, all jobs pass, release-gate skipping, Devin Review pass, no new findings.

Run ended the paragraph with "A status-only request wakes nothing", and nothing
distinguished that from a checkpoint asked inside an authorized ongoing
initiative. Read literally, the second fell under the first: a parent answered
with a report and stopped, leaving work its existing approval already covered.

Qualify the sentence instead of replacing it. A standalone status-only request
still wakes nothing. A checkpoint inside an authorized ongoing initiative is
handed to the responsible parent and handled there as a resume of the authorized
run, on the path the Resume row above already describes, re-evaluating
outstanding child results, pending decision requests, cleared blockers and empty
execution slots before continuing the successors that approval covers.

This adds no scheduler and no second writer: the same parent, children and
assignments are reused, and nothing that already has an owner is dispatched. The
handoff stays a manual push rather than automatic continuation, so OPS-8.1's rule
that no future wake-up is guaranteed is untouched, and an explicit status-only,
report-only, read-only or pause limit on the checkpoint still wins.

Confined to the "Keep a project run moving" paragraph.
The four-request table classified every "how is it going" as a read that wakes
nothing. That is the same defect the Keep a project run moving paragraph had:
read literally, a checkpoint arriving inside an execution approval that is still
in force fell under it, so the supervision reported and stopped while approved
work sat unfinished.

Qualify the one row. The read stays the default branch. Where this task
supervises the initiative and its approval is still in force, a checkpoint also
hands the pending approved work to the responsible parent on the resume path that
parent already has, and reports what was actually done.

The binding answer is unchanged and is now stated for both branches: a checkpoint
creates no supervisor, moves no ownership, and starts nothing for work that
already has an owner. An explicit status-only, report-only, read-only, plan-only,
pause or no-contact limit keeps the row's original no-wake reading.

Confined to that row.
The scan that fills empty capacity already existed, but nothing said when it
runs or what a hold means, and the two reads that would answer it had just
landed with no instruction naming them. So a parent learned a child had stopped
only if somebody told it, and "record a concrete dependency, conflict, ownership,
or capacity reason" let one sentence cover a blocker, an unproved owner and a
capacity nobody measured, which recover differently.

Name the forcing events inline, where they are always loaded: initial dispatch, a
child's completion, blocker or decision request, an integration landing, and every
resume or recovery. Before the turn ends the scan has run or the reason it could
not be read is recorded, because a final answer describing what would be
dispatched is not the scan.

Join the two reads to the rules that were already written. An issue with a
responsible child is not a candidate, and doctor --issue answers that from one
non-constructing read before anything is created. A child stopped for a person is
invisible to the reviewable reads, so dispositions-show enumerates them rather
than their silence being read as progress; it reports what the child emitted, so
OPS-8.1 still owns the emit and observation paths.

references/reevaluation.md carries what needs a table rather than a sentence: the
read behind each event, what the stopped-children reader does and does not answer,
the closed decision set with the condition that clears each value and the row it
rests on, and the per-candidate record with what each absence means. Capacity
words stay in start-policy, reader vocabulary in relay, the turn-ending
prohibition in OPS-8.1.

The set has no escalation value, so a review round count has nowhere to land. It
separates no capacity from capacity nobody measured, an unproved owner from two
the store reports, and an unreadable disposition from a contested one. task-packet
gains the field a checkpoint reads, since the record list had none and criterion
10 was unobservable without it.
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 20, 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
🔒 Security Review Completed 2026-09-20T20:04:24.408981Z 2601417 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.

devin-ai-integration[bot]

This comment was marked as resolved.

Seven findings, all real. The file restated relay.md's own vocabulary after
saying it would not, and the copies had already drifted from it; it is now the
pass-specific mappings and links, and relay.md keeps its semantics.

Three factual corrections. The forcing-event table disagreed with the
always-loaded list in SKILL.md: it dropped initial dispatch and promoted
capacity, edit overlap and new attachments to triggers, when those are inputs
read inside every pass. It listed linkage-attach, which mutates, as a read.

The ownership procedure used the wrong axis. assignment-find reports an
ambiguous project parent through its scope reading, not several responsible
children for one issue, so defer:ownership_ambiguous as written could never be
reached: holds true already ends the evaluation. It is now defer:scope_ambiguous
on the axis that command actually answers.

A declared supersession does not clear a contested execution disposition; only a
fresh generation does. And the set could not record a real contradiction in the
criteria, which the same paragraph said may travel upward, so
defer:criteria_contradiction is added. Retaining no review-round escalation
value stays deliberate.

The file also ended with a blank line, which git diff --check refuses.
defer:scope_ambiguous could not occur. The owning project parent is only read
where a live assignment exists, and that is exactly the case doctor --issue ends
as skip:already_owned; with holds false the scope reading is always unscoped. So
the value sat in a closed set promising a condition a later pass would re-read,
and nothing could ever set it.

Ownership is one question with one read. doctor --issue constructs nothing and
settles it: holds true reuses the existing child, holds false is dispatchable on
that axis, and holds null or an unusable state directory is unproved rather than
free. The second, store-constructing lookup is gone with the value it existed to
produce.

@devin-ai-integration devin-ai-integration 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.

Note

This report is out of date. Scroll down for Devin Review's latest report on this PR.

Devin Review found 1 new potential issue.

Devin Review

Comment thread plugins/crw/skills/crw-run/references/reevaluation.md Outdated
The rationale claimed a further lookup could only repeat doctor. That is wrong:
a project parent can be read without any assignment, on a different axis. The
pass stops at one read because issue-child ownership is what decides whether
this candidate may be dispatched, not because nothing else could be asked.
The ownership read was written as if a relay always answers. On an explicitly
direct assignment there is no store, so doctor --issue reports holds null, and
the rule turned that into defer:ownership_unverified for every ready issue. A
direct run would have dispatched nothing at all, which is the opposite of what
the pass exists for.

Scope both new reads to the execution mode this skill already determines, using
the same "where a relay holds the assignment" condition the rest of the file
uses. A direct assignment takes its owner from the coordination record and the
existing task, as everywhere else here, and is never held for the absence of an
answer from a relay it never used.
devin-ai-integration[bot]

This comment was marked as resolved.

The previous commit swung too far. Saying defer:ownership_unverified does not
apply to a direct assignment removed the only ownership hold the closed set has,
so a resumed direct run that cannot read its coordination record had no valid
decision: dispatch and open a second writer, or decline and record nothing.

Separate the two things that were conflated. The absence of a relay is not a
hold, because a direct run never uses one. A failed read is a hold in either
mode, because direct mode removes the relay lookup and not the obligation to
establish an owner, and an inaccessible record is not evidence that no writer
exists. The decision's evidence now names whichever read failed.
The criterion is that repeated review cost must not send an already approved
correction back to the user, and the skill never said so. It rested on the
closed decision set having no escalation value, which governs candidate holds
rather than corrections, so nothing reached the section that actually sends one.

State it where corrections are returned: the next round goes to the same task
with what changed, and the parent judges whether the evidence supports
continuing. New scope, new authority and a real contradiction in the criteria
stay decisions somebody else owns; a round count is not one, and neither is the
cost of having looked again.
The pass named merge-turn-show, region-show, capacity-show and
linkage-outstanding and left a reader to infer what their selectors, refusals
and absences meant. Both reviews raised it against this delivery, and it was the
weakest part of it: naming a command without saying what its silence means is
how a coordinator reads an empty answer as a settled one.

Document them where relay command usage already lives. An unregistered merge
turn answers ok false rather than an empty record, so a mistyped id is not read
as a released window. capacity-show carries headroom only when a scope is given,
and only for dimensions with a declared limit, so an undeclared scope is
unbounded by the store rather than known to have room. A region nobody proposed
has no row, so an absent overlap is unknown rather than none. And
linkage-outstanding is scoped to the project rather than the current parent,
because filtering by parent once let a replacement look as though it had no
outstanding work and a second replacement take the project without
acknowledging anything.

The three that go through the enforcement wrapper also carry unenforcedIndexes,
which tells a reader deciding whether to act on a contested owner that the
database is not stopping a second one either.
@thisisjun786
thisisjun786 merged commit 9d01c37 into dev Sep 20, 2026
9 checks passed
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