Repository navigation
Description
Observed
Run 3, unic-dlc-pr-review iteration 2 on PR 5881, byte-identical commit 08e2523 to iteration 1. The second review did not mention six of the first iteration's thirteen findings (confidence 78, 74, 72, 72, 64, 61, all Standards). reconcile returned:
{"iteration":2,"fixed":6,"still_present":7,"regressed":0,"new":4,"prior_count":13,"verdicts":13,"unverified_fixed":0,"unmatched_priors":0}
post then set threads 65901, 65904, 65905, 65906, 65909 and 65910 to Azure DevOps status fixed. Nobody changed the code and nobody resolved anything by hand.
unverified_fixed stayed 0 because it reads the PR's diff against its base, and the six files were in that diff. The evidence a fixed needs is the change between the two iterations, and the Box records no head commit per iteration.
Why it matters
A duplicate thread is noise a reader discards. A false fixed is a defect a reader stops looking for. On a repository with no CI the pull request is the only record, so this turns the reviewer's variance into false state on the Consumer's PR.
Evidence
- Findings register, § "G. What run 3 taught about the instrument", row G4: https://github.com/unic/unic-agents-plugins/blob/bcf688a/docs/research/2026-08-31-dlc-run-2-findings.md
- Run record and harvested artefacts:
~/Desktop/run3-parked/on the maintainer's machine (artefacts-908e3735…-pr-review-2038/findings.json,threads.json;az devops invoke … pullRequestThreadsfor PR 5881) - Dispatch record: #457 from comment 5698289748 down
Decisions
Grilled with the maintainer on 2026-10-27, under map #498.
- A
fixedneeds the finding's file to change between the two iterations. The evidence is the change between the prior iteration's recorded head and this iteration's head. The PR's diff against its base is never evidence for afixed. A change to the file is necessary. It is not proof that the fix is right, and that limit is accepted. - An omitted prior finding whose file did not change gets a verdict of its own,
unverified. It is neitherfixednorstill_present. A finding whose real fix landed in another file also lands here. That false open costs the author one click, while a falsefixedhides a defect. postreplies once to anunverifiedthread and does not change its status. It does not reply again in a later iteration while the finding staysunverified./pr-reviewreviews again on an unchanged head. It does not stop. A rerun is how apostthat failed halfway gets finished.- With no prior head to compare against, every omitted prior is
unverified. This covers the first iteration after this ships, whose prior iteration an older Box posted, and a prior head the clone cannot reach after a rebase or a force push. The summary tells the developer why and what is asked of them. - An omitted scoped finding is always
unverified. A finding whosefileispull request,work itemorrepositoryhas no file to check, so a person closes it. - A thread that is resolved and whose finding is reported again is reopened, whoever resolved it. This includes an
unverifiedthread a person resolved by hand.
Acceptance criteria
Every criterion names the diff it reads. "The change between the two heads" means git diff --name-only <prior head> <head>, where both heads are recorded iteration heads. "The PR's diff" means the diff against the PR's base, which prep computes today.
Recording the head
- Every iteration records the commit it reviewed, in the PR, in a place the next iteration's
prepreads back. The value comes fromgit rev-parse HEADin the reviewed tree, not from a model's account of it. -
prepemits the prior iteration's head, or states that there is none. "None" covers both a prior iteration that recorded no head and a recorded head the clone cannot reach after a fetch.
Classifying, in reconcile
-
reconcilewrites the list of files in the change between the two heads to the session directory, as the output of the git command, before it classifies anything. Everyfixedverdict can be checked against that file. - A prior finding with no match this run is
fixedonly when itsfileis a path and that path appears in the change between the two heads. Otherwise it isunverified. The PR's diff plays no part in this rule. - A prior finding with no match this run is
unverifiedwhenprepreports no prior head. No prior finding isfixedin that iteration. -
prepreadsunverifiedback as a prior verdict, alongsideopenandfixed, from what the prior iteration posted. A priorunverifiedfinding is then classified like anopenone:still_presenton a match,fixedby the rule above,unverifiedotherwise. -
reconcileemits anunverifiedcount.unverified_fixedis removed, because afixedthat rests on absence alone no longer exists. Every reader ofunverified_fixedinunic-dlc-pr-review.yamlreads the new count instead: thereview-gatemessage andpost's final line.unmatched_priorsstays, and stays the number that must be zero. - The "since iteration N−1" delta in the summary shows
unverifiedbesidefixed,still present,regressedandnew.
Writing to the PR, in post
- On an
unverifiedthreadpostposts one reply and leaves the thread's status as it was. The reply says that the review did not report the finding this iteration, that its file did not change since the prior iteration (or that the finding is scoped, or that there was no prior head), and that the author should check it by hand and resolve it if it is gone. A thread that already carries that reply from an earlier iteration gets no second one. -
postreads each thread's status before it acts. A thread that is resolved, and whose finding isstill_presentorregressedthis iteration, is reopened with a reply saying the finding was reported again in iteration N. Where the tracker has no reopen,postreplies on the thread. - When
prepreports no prior head, the summary carries a section that tells the developer, in plain words, why no finding could be ruled fixed (no recorded head, or the history was rewritten) and what is asked of them: check eachunverifiedthread by hand and resolve the ones that no longer apply. It also says that the check is automatic again from the next iteration unless the history is rewritten again. -
fixedkeeps today's behaviour inpost: reply "✅ resolved in iteration N" and resolve where the tracker can.
The four cases that prove it, and where each runs
Each case names the diff it reads.
- Identical head. Two iterations on one commit. The change between the two heads is empty. Every omitted prior is
unverified,fixedis 0, everyunverifiedthread stays unresolved and carries exactly one reply. A third iteration on the same commit adds no reply to those threads. This is run 3's case. - Rerun after a partial post.
postis killed after it has written at least one reply and before it finishes. A rerun on the same head ends with one thread per finding and no reply repeated on any thread, whatever the verdict. A reply counts as repeated when the thread already carries a reply for the same finding hash and the same verdict. To tell what is already posted,postreads the PR's existing threads and replies by their hidden markers. It never reads the killed run's session directory. So every replypostwrites carries a hidden marker with the finding's hash and the verdict it answers. That hash is the hash of the thread's own finding, the one the thread was opened with, never a hash the rerun computes fresh: the reviewer rewords, so a fresh hash would never count a reworded re-report as repeated. The rerun'spostcompares against the prior finding it matched inreconcile. The rerun counts as a new iteration (N+1), as today, because the killed run's summary already carries its iteration marker. - The finding's file changed. The change between the two heads includes the finding's file, and the review does not report the finding again. The finding is
fixedand its thread is resolved. - Only another file changed. The change between the two heads is not empty and does not include the finding's file, and the review does not report the finding again. The finding is
unverified, and its thread stays unresolved with one reply.
Where each case runs, per map #498 § Run 4's shape:
- Identical head: run 4's iteration 2, on the same head as iteration 1.
- Rerun after a partial post: run 4's rerun of iteration 2, on the same head.
- The finding's file changed, and only another file changed: run 4's review after the single fix commit, checked against
git diff --name-onlybetween the recorded heads of the rerun and that review.
The rerun is numbered N+1 on the pull request, so the review the map calls iteration 3 carries a higher number there.
Documents
-
apps/claude-code/unic-archon-dlc/docs/boxes/unic-dlc-pr-review.mdlistsunverifiedwherever it lists the verdicts, and says whatpostdoes with it and with a resolved thread whose finding is back. - If the change adds a node to
unic-dlc-pr-review.yaml,apps/claude-code/unic-archon-dlc/docs/architecture/20260925-unic-dlc-pr-review-pipeline.jsonis updated and both PNGs are exported again. The decisions above add no node, so this is expected to need nothing. -
apps/claude-code/unic-archon-dlc/CHANGELOG.mdcarries an entry under## [Unreleased].
What a run here does not prove
- The pull request states that the change is unproven in the Consumer until a Consumer run reads it. A run in this repository does not prove it.
Not decided here, on purpose
- The exact wording of the
unverifiedreply, the reopen reply and the summary section. The criteria fix what each must say, not the text. - Where in the PR the head is recorded. The criteria require only that the next iteration's
prepreads it back.
Activity
orioltf commentedon Oct 27, 2026
Stale — do not follow. The criteria are approved and the fix is dispatched under
/afk-loop 498; the opener for the fix is the newer comment that starts with**Opener for #482**.Opener — How to start this session (written 2026-10-27 by
unic-sdlc-orchestrator-7, at dispatch)What this session produces
Approved acceptance criteria in this ticket's body, then the label
ready-for-agent. Nothing else. The fix runs later under/afk-loop 498. This ticket blocks #502, run 4.Start: the maintainer types
/wayfinder 498 #482. This ticket's parent is #498. When the grilling starts, the maintainer types/grill-with-docs. Both carrydisable-model-invocation, so the session cannot invoke them itself.Do not close this ticket. This overrides
/wayfinderstep 4. This stream grills a ticket into its own criteria and implements it under the same number. Do not invoke/implement,/tddor/to-tickets. Keepneeds-specsuntil the maintainer approves, then replace it withready-for-agent.Read in this order
apps/claude-code/unic-archon-dlc/.archon/workflows/unic-dlc-pr-review.yamlonorigin/develop:prep(howprior_findingsandprior_verdictare read),reconcilestep 3 (thefixed,retiredandunverified_fixedrules),review-gate, andpost(what afixedverdict does to a thread).docs/boxes/unic-dlc-pr-review.md, the part on re-review.The trap that costs an hour
Assuming
unverified_fixedalready covers run 3's case. Since the ticket was filed,reconciledefinesunverified_fixedas afixedverdict where "THIS run's diff does not touch that file at all". But "this run's diff" is the PR's diff against its base. In run 3, iteration 2 ran on a byte-identical commit, and the files of the six omitted findings were in the PR's diff, so the rule counts zero. That is what run 3 recorded. The evidence afixedneeds is the change between the two iterations, and the Box records no head commit per iteration today: nothing inpreporreconcilenames one. A criterion that tightensunverified_fixedwithout saying which diff it reads passes review and repeats run 3.What this ticket does not decide yet
Each of these is a question for the maintainer. None is yours to settle with a plausible default.
fixed. Either the prior finding's file changed between the prior iteration's head and this one, which needs that head recorded, or the prior finding is re-checked against the current tree. Or both.postdoes with afixedit cannot verify. Reply without resolving, or resolve with anunverifiedmarker. Todaypostreplies "✅ resolved" and sets a resolved status wherever the tracker has one.still_present,unverified_fixedor a verdict of its own./pr-reviewon the same head commit as the prior iteration should re-review at all, or carry the prior verdicts forward.Other traps
unic-dlc-pr-review.yaml. unic-archon-dlc: ADR links in commands/*.md resolve against the Consumer's repository #556 isready-for-agentunder wayfinder: unic-archon-dlc is prose, and proven at a Consumer #373 and waits on bug(unic-archon-dlc):/qaends green on paths where nothing merged #652 and bug(unic-archon-dlc): open-pr precedes its gate, and a config-value gate has no safe middle #439. If this ticket goesready-for-agent, ask the maintainer for a nativeblocked_byedge unic-archon-dlc: ADR links in commands/*.md resolve against the Consumer's repository #556 ← bug(unic-archon-dlc):reconcilemarks a finding fixed when the next review omits it, andpostresolves the thread #482, so the two runs never edit the file at once./pr-reviewmakesapps/claude-code/unic-archon-dlc/docs/architecture/stale for the pr-review pipeline. If the criteria add a node, they require its JSON updated and both PNGs exported again.The bar that proves it
Run the four reads from
docs/agents/dispatching-and-learning.md§ Before you post one on the criteria as a set. Then check:/pr-reviewon a byte-identical head, whose review omits a prior finding, leaves that finding's thread unresolved and does not call it fixed.fixed.A false pass is a stricter
unverified_fixedthat still reads the PR's diff: it is counted, it stays zero on run 3's case, andpoststill resolves the thread.On landing
unic-sdlc-orchestrator-7with the link. The orchestrator reads the criteria as one set and replies.needs-specswithready-for-agent, keepp1unless the maintainer moves it, and leave it unassigned for/afk-loop 498.Report back
Review and handover
There is no pull request. The maintainer approves the criteria in the session. The orchestrator reads them as one set before the label goes on. Implementation runs under
/afk-loop 498, which this seat records as unproven in the Consumer until a Consumer run reads it.orioltf commentedon Oct 27, 2026
Body rewritten after grilling with the maintainer, 2026-10-27.
What changed:
fixedneeds the finding's file to change between the prior iteration's recorded head and this one. An omitted prior whose file did not change gets a new verdict,unverified.postreplies once and does not resolve its thread.unverified_fixedis to be removed. It read the PR's diff against its base, which is why it stayed 0 on run 3.Labels stay as they are until
unic-sdlc-orchestrator-7has read the criteria as one set.orioltf commentedon Oct 27, 2026
Body amended after the orchestrator's set read, 2026-10-27. The cause is the map change on #498: run 4 no longer runs a byte-identical bench.
posttells what is already posted from the hidden markers on the PR's threads and replies, so every reply carries a marker with the finding's hash and its verdict. The maintainer decided that the rerun counts as a new iteration (N+1), as today.git diff --name-onlybetween the recorded heads of the rerun and the review after the fix commit.orioltf commentedon Oct 27, 2026
Body amended, 2026-10-27. The partial-post case now says whose hash a reply's marker carries: the hash of the thread's own finding, the one the thread was opened with, never a hash the rerun computes fresh. Then
ready-for-agent,p1, no assignee, and #556 is now blocked by this ticket.orioltf commentedon Oct 27, 2026
Opener for #482
Written 2026-10-28 by the
/afk-loop 498orchestrator, at dispatch. It supersedes the grilling opener above, whose job ended when the criteria were approved.What this session produces
One pull request to
developthat changesapps/claude-code/unic-archon-dlc/.archon/workflows/unic-dlc-pr-review.yamland its documents so that an omitted prior finding isfixedonly when its file changed between two recorded iteration heads, andunverifiedotherwise. The criteria in this ticket's body are the spec. Do not invoke/tddor/to-tickets: this repository's product here is prose, and the bar is a read, not a test (AGENTS.md§ Acceptance criteria are prose).Read in this order
unic-dlc-pr-review.yamlonorigin/develop:prep§ 4 (howprior_findingsandprior_verdictare read),prep's diff step (whereHEADandSESSION/changed-files.txtcome from),reconcilesteps 2 to 6 (the verdicts,retired,unverified_fixed, the summary frame, the fixed list and its markers, and the thread plan), thereview-gatemessage, andpost(the summary update, the per-line kinds, and the closing line).apps/claude-code/unic-archon-dlc/docs/boxes/unic-dlc-pr-review.md, the part on re-review.The trap that costs an hour
A reader with no writer.
prepcan only read a prior head, a priorunverifiedverdict, or an earlier reply back from text that an earlier iteration posted. So each new thingprepreads needs a named place wherereconcileorpostwrites it, in the same pull request:reconcilestep 5 writes the summary, andpostupdates that summary in place. A head thatpreplooks for and nothing writes reads as "no prior head" on every iteration, sofixedis 0 forever and the identical-head case passes for the wrong reason.unverifiedverdict: today the summary listsfixedfindings with their markers, andprepreadsprior_verdictfrom that list. Anunverifiedfinding needs the same, orprepreads it back asopen. That reads the right verdict by accident, but a scopedunverifiedfinding has no thread, so the summary is the only place its hash survives.postmust find an earlier reply by its hidden marker, which carries the thread's own finding hash and the verdict. Read the body's partial-post case for whose hash that is.For each one, trace it once from writer to reader on paper before you edit.
What this ticket does not decide
The body leaves these open on purpose. Pick, write the choice and the reason in the PR body, and keep it consistent everywhere:
postalready rewrites the summary in place on every run. The value must come fromgit rev-parse HEADin the reviewed tree, written to a file in the session directory by the command, never retyped by a model.finding=<hash>or is a marker of its own. If it reuses it,prepmust not read a reply as a second prior finding, andpostmust still find a thread by its first comment.unverifiedreply, the reopen reply and the no-prior-head section. The body fixes what each says, not the text.Other traps
retiredis unchanged, and must stay that way. A priorfixedwith no match is stillretired. A priorunverifiedwith no match isfixedorunverifiedby the new rule, neverretired. Write the rule for eachprior_verdictvalue explicitly.unverified_fixedhas readers outsidereconcile: itsoutput_format, thereview-gatemessage, andpost's closing line. Grep the file for every one before you call it removed.AGENTS.mdnames that as a defect. The four cases run in the Consumer, in run 4.postmust read a thread's status before it acts, and a resolved thread whose finding is back gets reopened. Ask the tracker whether reply and status change are one call or two, as the file already says forfixed.cd. The NDA hook refuses aghcommand that changes directory.The bar that proves it
Read the four cases from the body against the file at your head, and for each one follow it from
prepthroughreconcileandthreads.jsontopost, naming the line that produces each verdict and each reply. The PR body states the walk for each case in a few lines.A false pass:
reconcileemitsunverified, butpostdedupes replies against a hash this run computed, or against the session directory. Then the identical-head case looks right on iteration 2 and adds a second reply on iteration 3.On landing
apps/claude-code/unic-archon-dlc/CHANGELOG.mdunder## [Unreleased], and commit it with the change.pnpm --filter unic-archon-dlc bump minor, because the plugin is0.xand the Box's behaviour changes. Commit the result on its own aschore(unic-archon-dlc): release <version>.Closes #482.Report back
Report in your final answer, as your worker prompt's step 7 says, and stop after the handover. The orchestrator may continue you with fix rounds.
Review and handover
The orchestrator runs the review rounds, sends you the findings to fix, requests the Copilot review, and merges when the gate holds. You do not merge, and you do not answer review threads.
unverifiedfinding has no way out of the ledger #662