Skip to content

cluster-PR mode 強制 PR 與 direct-commit path 衝突:override 未文件化且 --no-pr 行為未定義#99

Merged
kiki830621 merged 3 commits into
mainfrom
idd/96-cluster-pr-mode-pr-direct-commit-path-ov
May 19, 2026
Merged

cluster-PR mode 強制 PR 與 direct-commit path 衝突:override 未文件化且 --no-pr 行為未定義#99
kiki830621 merged 3 commits into
mainfrom
idd/96-cluster-pr-mode-pr-direct-commit-path-ov

Conversation

@kiki830621
Copy link
Copy Markdown
Contributor

@kiki830621 kiki830621 commented May 19, 2026

Refs #96

Summary

Documents cluster mode as a precondition that pre-empts the pr-flow.md resolution algorithm, with explicit override notice (mirror fork detection) when --no-pr / pr_policy:"never" collides with cluster mode. Implements Option A from the diagnosis (user-selected in idd-all session).

The cluster-PR-mode-vs---no-pr rule was previously split across 3 files (pr-flow.md algorithm table didn't mention it; idd-implement SKILL line 49 said "doesn't accept --no-pr" without specifying behavior; batch-and-cluster.md line 133 stated the rule but in cross-references). Three files contradicted; behavior on collision was undefined.

Changes (1 commit, 3 files, +23/-3)

  • references/pr-flow.md — add ### Cluster mode override subsection + algorithm-table preface note
  • references/batch-and-cluster.md — line 133 → pointer to pr-flow.md new section
  • skills/idd-implement/SKILL.md — line 49 stub → spec'd behavior with explicit override notice format

Decision: Option A

Diagnosis surfaced 3 candidate approaches; user picked A (maintain forced PR, but explicit + consistent):

  • Smallest change (3-file doc tweak)
  • Mirrors existing fork detection pattern (consistency principle)
  • Backward-compatible (single-issue invocation behavior unchanged; cluster carve-out only fires on ≥2 #N)

Options B (cluster accepts --no-pr and degrades to shared branch) and C (AskUserQuestion on collision) deferred — re-open as follow-up if A proves insufficient in practice.

Checklist

  • Diagnose (comment 4483898985)
  • Implement (3 commits: cbe6f5d R1 doc + 5351116 R2 bash + 04c51cb R3 doc fix)
  • Verify — 6-AI × 2 rounds: R1 CONDITIONAL → R2 6/6 PASS (R2 master)
  • Pending: human review of this PR + /idd-close #96 after merge

Related


Generated by IDD /idd-all 96. Do NOT add a GitHub close trailer (Closes/Fixes/Resolves) — IDD discipline requires manual /idd-close after merge to enforce checklist gate + closing summary.

…Refs #96)

cluster-PR mode 強制 PR path 的規則原本散落在 idd-implement
SKILL.md:49 + batch-and-cluster.md:133,canonical 演算法表
pr-flow.md 沒提此 carve-out — 三檔互相矛盾;`--no-pr` 撞 cluster
時 flag 被無聲吃掉、行為亦未指定 (abort / warn / silent ignore)。

採用方案 A (issue body 列的 3 案,user 於 idd-all 對話選 A):
維持強制,但明示 + 一致。

pr-flow.md:
- Resolution algorithm 表上方加註 cluster mode 是 precondition,
  pre-empts 整張表 (見新節)
- 新增 `### Cluster mode override` subsection,規格 cluster
  pre-emption + explicit override notice 格式 (mirror fork
  detection 的 pattern):
    → cluster mode (N issues) → PR path enforced (overriding ...)
  並寫明「no abort, no silent ignore」、single-issue 行為不變

batch-and-cluster.md:
- line 133 cross-reference 從規則陳述改為指向 pr-flow.md 新節
  的 pointer,rationale (cluster on direct-commit = stacked
  half-isolated changes) 整段搬到 pr-flow.md 新節為 source of
  truth

idd-implement SKILL.md:
- line 49「不接受 --no-pr」stub 升格為 spec'd behavior 描述,
  指向 pr-flow.md 新節

Backward compat: single-issue invocation 行為完全不變 (cluster
carve-out 只在 ≥2 #N 觸發);既有 cluster --pr explicit caller
不受影響。

Diagnose: see issue #96 comment 4483898985
Implementation Plan: see issue #96 comment 4483913507
@kiki830621
Copy link
Copy Markdown
Contributor Author

Requirements review (PR #99 / #96)

Verdict: CONDITIONAL PASS

Coverage matrix

Defect (#96) PR #99 addresses? Notes
L1 — pr-flow.md algorithm table had no cluster carve-out (3 files contradicted) yes pr-flow.md:18 adds bold preface declaring cluster mode pre-empts the table; new ### Cluster mode override subsection (lines 46-64) is now the canonical source; batch-and-cluster.md:133 rewritten as a pointer to that section; idd-implement/SKILL.md:49 also links to it. Single source of truth restored.
L2 — cluster-forced PR had no override notice (asymmetric with fork) partial (spec only) Override notice format → cluster mode (N issues) → PR path enforced (overriding --no-pr / pr_policy=never) is now specified in pr-flow.md:55 and echoed in idd-implement/SKILL.md:49, mirroring fork detection's text pattern. But the bash in idd-implement/SKILL.md Step 0.5 lines 108-144 has zero cluster detection and zero echo — only PR_FLAG/IS_FORK/PR_POLICY branches. The fork notice at line 131 has no cluster sibling. So users still won't see the notice at runtime.
L3 — --no-pr + cluster behavior undefined yes pr-flow.md:58 explicitly resolves the three candidates: "No abort, no silent ignore" → proceed as PR after printing the notice. idd-implement/SKILL.md:49 repeats verbatim. Behavior is now spec'd unambiguously.

Findings

Recommendation

CONDITIONAL PASS. The PR closes the documentation-contract part of #96 cleanly (L1 ✅, L3 ✅, L2 spec ✅), which is what Option A explicitly bought. The bash implementation of the override notice is the one piece of #96's Expected section that doesn't ship in this PR.

Two acceptable paths:

  1. Merge as-is + file follow-up issue for "wire cluster override notice echo in idd-implement Step 0.5 bash" — track the L2 runtime gap as known follow-up. Justifiable because the user explicitly chose Option A's documented "smallest change" scope, and the Implementation Plan flagged this out-of-scope ex ante. Honest, not a surprise.

  2. Block merge until Step 0.5 bash gains a [ "$ARGC_HASHES" -ge 2 ] cluster branch printing the spec'd notice. Approx. 5-line addition. This would fully close cluster-PR mode 強制 PR 與 direct-commit path 衝突:override 未文件化且 --no-pr 行為未定義 #96 in one PR with no follow-up debt.

Option 1 is reasonable given the explicit Plan-stage scope agreement and trivial echo cost; recommend Option 1 + immediate filing of the follow-up issue so the L2 runtime gap doesn't drift.

@kiki830621
Copy link
Copy Markdown
Contributor Author

Logic reviewer verdict (independent of other AIs)

Verdict: ⚠️ PASS with non-blocking findings — spec is internally coherent and the canonical-table-vs-carve-out logic resolves correctly, but several edge cases and a code/doc gap deserve explicit treatment before this can claim "single source of truth" status.

Findings

🔴 HIGH — Code/doc divergence un-flagged (Q4)
The doc spec now prescribes Phase 0.5 behavior ("Phase 0.5 prints → cluster mode (N issues) → PR path enforced ..."), but the bash block in skills/idd-implement/SKILL.md:108-144 shows no cluster detection — it parses --pr/--no-pr, then fork, then pr_policy, then ask. The override notice is documented but unimplemented. The Implementation Complete comment acknowledges this ("Phase 0.5 實作落實留作下游 follow-up(若必要)") but the references file does not say "desired behavior, code not yet aligned". Reader of pr-flow.md § Cluster mode override will reasonably assume the notice fires today — it doesn't. Recommend: add an explicit "Implementation status" line in the new subsection (e.g., > Status: spec'd; Phase 0.5 bash in idd-implement Step 0.5 will be updated in a follow-up to detect cluster mode and emit this notice — see #NNN), or file the follow-up before merging.

🟠 MEDIUM — Two pre-emptions, no precedence (Q1)
Both fork detection and cluster mode are described as "precondition that pre-empts" the algorithm table. The spec does not say what happens when BOTH apply (fork repo + ≥2 #N). Both force PR path → no semantic conflict on outcome, but the notice format is undefined: does Phase 0.5 print both notices? cluster only? fork only? The simplest answer is "both fire, fork first" (fork is structural/repo-level, cluster is per-invocation), but the spec is silent. Recommend: one sentence: "When both fork and cluster mode apply, both override notices print (fork first, then cluster); outcome is identical (PR path)."

🟠 MEDIUM — Override notice format is not parallel (Q2)
Fork notice: repo is a fork → PR path enforced (subject → verb).
Cluster notice: → cluster mode (N issues) → PR path enforced (overriding --no-pr / pr_policy=never) (leading arrow + double-arrow + parenthetical).
These are not parallel in structure even though the spec claims to "mirror fork detection." Also: the parenthetical overriding --no-pr / pr_policy=never lists both conditions unconditionally — if only --no-pr collided, the notice still mentions pr_policy=never (and vice versa), which is misleading. Recommend: either harmonize fork notice to → repo is a fork → PR path enforced (add arrow for consistency) and make cluster notice cite the actual triggering condition, OR explicitly say "notice format is fixed regardless of which collision triggered".

🟡 LOW — Cluster detection trigger ambiguity (Q3)
"≥2 #N invocations" is unambiguous for distinct integers, but the spec does not address: (a) duplicate #N (#34 #34 — 2 tokens, 1 unique issue; should this trigger cluster?), (b) interleaved non-#N tokens (#34 --pr #36 — currently the batch-and-cluster.md parsing rule says "tokens matching ^#\d+$ before any --flag", which would parse #34 only and miss #36). The existing batch-and-cluster.md:47 parsing rule answers (b) but not (a). Recommend: add a half-sentence to the new subsection: "Duplicate #N tokens are de-duplicated before the ≥2 count; #34 #34 resolves to single-issue mode, not cluster."

🟡 LOW — --pr + --no-pr collision unhandled in spec (Q2 part 2)
The new subsection covers --no-pr vs cluster, but if a user passes BOTH --pr and --no-pr (parse error), the existing Step 0.5 bash silently lets the last-wins (the case loop overwrites PR_FLAG per iteration). No abort, no warning. Not introduced by this PR, but the new subsection's "mirror fork detection" framing tempts readers to assume input validation exists. Recommend (out of scope, but worth a follow-up issue): make --pr + --no-pr together a parse-time abort.

🟢 LOW (verified clean) — Anchor slug (Q5)
GitHub slugifies ### Cluster mode override to #cluster-mode-override (lowercase, spaces→hyphens, no punctuation present). Both cross-references (batch-and-cluster.md:133 and skills/idd-implement/SKILL.md:49) resolve correctly. ✅

🟢 LOW (verified clean) — Single-issue backward compat (Q6)
The new preface note **Cluster mode (≥2 \#N` invocations) is a precondition that pre-empts this table**` is placed above the algorithm fence, with a hyperlinked drill-down. Single-issue readers see the note, follow the link only if they care, and the table rows 1-7 are untouched. Reading-order is monotonic (precondition → table → carve-outs); no ambiguity introduced. ✅

Logical consistency summary

Concern Internally consistent?
Cluster forces PR (claim) ✅ Consistent across 3 docs
Override notice spec'd ✅ Documented
Override notice implemented ❌ Bash unchanged (HIGH)
Fork + cluster co-occurrence ⚠️ Undefined (MEDIUM)
Notice format parallelism ⚠️ Claim ≠ reality (MEDIUM)
Trigger edge cases ⚠️ Duplicates undefined (LOW)
Anchor resolution ✅ Slugifies correctly
Backward compat ✅ Preserved

Recommendation

Merge eligible after addressing HIGH (add Implementation Status disclaimer or file follow-up issue tracking the Phase 0.5 bash update). The MEDIUM findings are spec-clarity polish — fix-in-place is cheap (≤5 lines added to the new subsection) and improves the "single source of truth" claim. LOW findings can be deferred to follow-up issues.

The core logic — making cluster a documented pre-emption parallel to fork — is sound and resolves the #96 three-way doc contradiction. The remaining gaps are about completeness of spec coverage, not about logical contradictions in what was added.

@kiki830621
Copy link
Copy Markdown
Contributor Author

Security Review — PR #99

Reviewer: Security (IDD verify ensemble)
Verdict: ✅ No security concerns found — PR is documentation-only and introduces no exploitable surface.

What I checked

PR #99 is doc-only (references/pr-flow.md, references/batch-and-cluster.md, skills/idd-implement/SKILL.md, +23/-3). It defines/documents cluster-mode-override semantics but adds no executable logic, no new bash, no schema, no config field, no flag, no permission, no network call. The override behaviour itself is already implemented in idd-implement Phase 0.5 (the existing fork-detection codepath is the documented mirror). The PR just makes the existing precedence visible.

Five-lens evaluation:

  1. Spec → behaviour implication (push/branch abuse via forced PR path)
    The override forces PR path → git push -u origin idd/cluster-<slug> + gh pr create --base $DEFAULT_BRANCH --head $BRANCH --repo "$GITHUB_REPO" (pr-flow.md:116, 141). All values flow from $GITHUB_REPO (config-resolved) and a sanitized $BRANCH (tr | sed filter to [a-z0-9-], 40-char cut — pr-flow.md:92-95). No user-controlled token reaches gh / git push. An attacker controlling cluster invocation cannot redirect push to a fork/alien remote — origin is fixed, and --repo is parameterised from config, not from $@. No abuse vector.

  2. Information disclosure via override notice
    Notice content: → cluster mode (N issues) → PR path enforced (overriding --no-pr / pr_policy=never). N is the count of #NNN tokens — no issue numbers, titles, or bodies leaked. Even if N were the numbers themselves, IDD already echoes the issue list during normal operation. No new disclosure channel.

  3. Cross-reference / anchor manipulation
    New anchor #cluster-mode-override is referenced from batch-and-cluster.md:133 and skills/idd-implement/SKILL.md:49. Anchor rename in a future PR would silently break two links — classic doc-rot, not a security issue. Mentioning here for completeness; mitigation is a future link-checker, not blocking for this PR.

  4. Backward-compat shim — single-issue cluster trigger via malformed args
    Cluster detection is ≥2 #NNN tokens (batch-and-cluster.md:19, 63). Args are shell-split ($@ whitespace tokens) before #N pattern-match. A single arg "#34 #36" (quoted by user) would tokenise as one shell arg → not match ≥2 #N tokens → no cluster trigger. A user invoking idd-implement '#34 #36' (quoted) gets single-mode + likely a "no such issue" failure downstream, not a privilege/path upgrade. Conversely, no way to single-issue invocation accidentally trip cluster path. No injection vector.

  5. Auto-close trap pre-screen (Step 0.8 defence-in-depth)
    Scanned full diff for Closes #<digit> / Fixes #<digit> / Resolves #<digit> (case-insensitive, with optional colon/dash):

    $ gh pr diff 99 | grep -nE 'Closes #[0-9]+|Fixes #[0-9]+|Resolves #[0-9]+|Closed #[0-9]+|Fixed #[0-9]+|Resolved #[0-9]+'
    (no matches)
    

    The override notice example uses --no-pr and pr_policy=never — neither is a GitHub close keyword. PR body and commit messages should still be checked at squash-merge time, but the diff itself is clean.

Findings

Severity Finding
None.

Recommendation

APPROVE from security perspective. Doc-only PR, override notice mirrors a pattern (fork detection) already exercised in production, no new attack surface introduced. The cluster precedence was already enforced in code (see issue #96 root cause: behaviour was correct but undocumented); this PR aligns documentation with reality. Merge is safe pending other reviewers' verdicts and the standard Step 0.8 auto-close trap scan on the final squash-merge commit body.

@kiki830621
Copy link
Copy Markdown
Contributor Author

Devil's Advocate review (PR #99 / #96)

Verdict: CONDITIONAL PASS — but only because Option A's own scope contract excuses the worst flaw. If you take the PR at face value as "fixes #96", it is closer to FAIL. Pick one of those framings honestly before merging.

Objection 1 (STRONG) — the spec/code gap is the L2 defect re-laundered as a feature

pr-flow.md:55 and idd-implement/SKILL.md:49 now both spec the override notice text. But idd-implement/SKILL.md Step 0.5 bash (lines 108–144) has zero cluster detection. The block branches on PR_FLAG / IS_FORK / PR_POLICY and nothing else; the fork notice at line 131 (echo "→ Repo is a fork; PR path enforced.") has no cluster sibling. So the observable L2 symptom #96 reported — idd-implement #34 #36 --no-pr silently swallowing the flag — persists byte-for-byte after this PR merges. The doc now promises a notice that the code does not emit.

That is arguably worse than the status quo. Before: 3 files contradicted, but at least the silent override was consistent with the canonical table. After: 3 files agree, all promise a runtime notice, and the runtime emits nothing. A user who reads pr-flow.md, sees the override notice spec, runs cluster + --no-pr, and gets no notice will reasonably conclude the IDD plugin is broken — because by its own canonical doc, it is. Doc-ahead-of-code is a known anti-pattern; this PR creates one in the exact subsystem #96 cited as the credibility loss.

The Implementation Plan's defense ("改動 trivial,留作下游 follow-up") makes this a deliberate gap. Trivial cost (≈ 5-line [ "$ARGC_HASHES" -ge 2 ] branch + echo) + high contract value (closes L2 fully in same PR) = no defensible reason to defer. The Requirements reviewer already flagged this as MEDIUM. I would argue HIGH.

Objection 2 (STRONG) — Option A cements the design tension instead of resolving it

The diagnosis observed (verbatim) that batch-and-cluster.md:133's forcing rationale "only holds when the user starts from default branch". On a feature branch idd/foo-baz, cluster + direct-commit is N Refs #N commits on that branch — a legitimate workflow, not pollution of default. Option A doesn't address that asymmetry: it labels the override visible and calls it done.

That means three months from now, the next user who runs cluster from a feature branch hits the same surprise, reads the new override notice, and asks "why is it doing this to me? I'm not on default." The notice doesn't answer that question — it just makes the override less invisible. The Diagnosis even said "「強制 PR」的理由部分成立(default branch 場景)、但被誇大(feature branch 場景理由不適用)". Option A perpetuates the exaggerated rationale.

This isn't a blocker for this PR, but it is a flag that #96 will likely reopen. Option B (cluster accepts --no-pr when on non-default branch) was the conceptually cleanest resolution and was rejected for "改動量 中" — modest cost. The Plan-tier EnterPlanMode was skipped (per (PR, unattended) mode contract, see issue Step 3.4 footnote), so this trade-off was made via inline AskUserQuestion in idd-all without seeing B/C laid out side-by-side as full Implementation Plans. That is exactly the failure mode idd-plan exists to prevent.

Objection 3 (MEDIUM) — override notice is too quiet to count as recourse

→ cluster mode (N issues) → PR path enforced (overriding --no-pr / pr_policy=never) — one line, no color, no separator, in the same stream as everything else Phase 0.5 prints. A user who set pr_policy: "never" because they actively dislike PR workflows will scroll past this in milliseconds when the cluster PR they didn't want appears in gh pr list. "We told you in scrollback" is poor recourse for a config-overriding action.

Fork detection gets away with the same one-liner because fork-PR is a technical necessity (can't push to upstream). Cluster-PR is a design preference — and the diagnosis admits the preference is exaggerated on feature branches. A discretionary override deserves louder signaling than a forced one. Either AskUserQuestion (Option C, attended) or abort-with---pr-required-error (forces re-invocation) would respect pr_policy: "never" users meaningfully. The current notice respects them in form only.

Objection 4 (LOW) — anchoring drift not actually reduced

#96's grievance was "3 files contradicting". After this PR there are still 3 places referencing cluster behavior: pr-flow.md (canonical), batch-and-cluster.md:133 (pointer), idd-implement/SKILL.md:49 (pointer + restated notice text). The restated notice text in SKILL.md line 49 is the same kind of duplication #96 complained about — the next maintainer who tweaks the notice format in pr-flow.md will likely forget to update SKILL.md line 49, and the drift problem recurs. A truly clean fix would have left SKILL.md line 49 as pure pointer (no notice text restated).

Recommendation

CONDITIONAL PASS with one hard condition: add the 5-line cluster branch to Step 0.5 bash in the same PR. Otherwise L2 is shipped as broken-by-design.

If user insists on Option A's "smallest change" framing and refuses the bash addition, downgrade to PASS-with-debt and file the follow-up issue before merge (not after) — the doc-ahead-of-code window must be < 1 day, not "someday". Objections 2/3/4 are deferred to a future re-open of #96 if the design tension surfaces again, which the diagnosis itself predicted.

Be honest about which framing you're choosing.

@kiki830621
Copy link
Copy Markdown
Contributor Author

Regression review — PR #99

Reviewer: Regression (1 of 6-AI verify pool)
Scope: Cross-file consistency, anchor integrity, behavior preservation for single-issue path, sibling-doc drift.
Method: full repo grep sweeps for stale verbatim quotes + manual read of touched + adjacent files.

Verdict: PASS WITH FINDINGS

The doc-only diff is clean on stale-quote sweep and anchor-stable, but introduces a documentation/code divergence in idd-implement Step 0.5 that fails the cross-file integrity check. Findings below are non-blocking for merge-as-doc-only, but a follow-up issue (or in-PR fix) is warranted before any caller claims the override notice is implemented.

Findings

[HIGH] Doc claims behavior the code does not implementskills/idd-implement/SKILL.md:49 (NEW) and references/pr-flow.md:52-58 (NEW) both state "Phase 0.5 prints → cluster mode (N issues) → PR path enforced ... (mirror fork detection)". But the actual Step 0.5 bash block (skills/idd-implement/SKILL.md:108-144) is untouched by this PR: it has no cluster detection branch, no N_ISSUES ≥ 2 check, no override echo. The fork branch at line 129-131 has its analogous notice; cluster has none. This makes the doc a promise the code does not fulfill — a --no-pr user running idd-implement #34 #36 #38 --no-pr today still silently gets direct-commit (the failure mode #96 was filed to fix), exactly the regression the PR purports to solve. The PR is doc-only; that's stated. But three call sites now contradict the actual bash. Recommend: open follow-up issue (or expand this PR) to add the cluster carve-out into the bash block — until then mark the doc with "(planned, not yet wired in Phase 0.5 bash)" or similar.

[MEDIUM] Step 0.5 numbered algorithm summary is now staleskills/idd-implement/SKILL.md:99-106 reproduces a 6-line algorithm 1. --pr → PR / 2. --no-pr → direct-commit / ... without the cluster pre-emption preface that pr-flow.md just gained at line 18. A reader who lands directly on Step 0.5 (the most common entry point — they're implementing, not browsing references) sees no cluster carve-out at all. Fix: add a 7th preface line 0. ≥2 #N invocations → PR path (cluster mode pre-empts; see pr-flow.md § Cluster mode override) or restructure as a preface bullet.

[LOW] No regression in idd-verify / idd-close docs even though pr-flow.md scope includes themreferences/pr-flow.md:48 (NEW) says cluster mode = idd-implement #34 #36 #38, idd-verify, or idd-close invoked with ≥2 #N arguments. But neither skills/idd-verify/SKILL.md nor skills/idd-close/SKILL.md mention the --no-pr collision or the override notice. This is not a regression of THIS PR (those skills were already silent), but the new pr-flow.md text broadens the contract surface — verify/close skill docs are now under-documented relative to the new canonical reference. Acceptable trade-off given the PR is scoped to "doc the override".

[INFO] Anchor slug verified stable — GitHub auto-slugs ### Cluster mode overridecluster-mode-override. Three cross-refs (pr-flow.md:18, batch-and-cluster.md:133, idd-implement/SKILL.md:49) all use the exact slug #cluster-mode-override. No silent breakage.

[INFO] No stale verbatim quotes — Grep sweep for "never direct-commit", "stacked half-isolated", "不接受 \--no-pr", "不接受 \--no-pr`"returns **zero matches outside the diff'd files**. The rationale text moving frombatch-and-cluster.md:133intopr-flow.mddid not orphan any callers.usecase-routing.md, external-agent-delegation.md, chain-flow.md, idd-all/SKILL.md, idd-verify/SKILL.md, idd-close/SKILL.md, CLAUDE.md, README.md, CHANGELOG.md` — none reference the old verbatim text.

[INFO] Algorithm-table preface wording is surgical — The new preface at pr-flow.md:18 adds bold for the cluster precondition and an anchor link. A single-issue reader who doesn't need cluster context can skip it (it's clearly a "see X below" pointer, not a redefinition). The original algorithm table is preserved verbatim. No reader-flow regression.

[INFO] Branch naming and PR title prefix preservedidd-implement/SKILL.md:49 rewrite kept both idd/cluster-{slug} branch name and cluster: PR title prefix. No information loss.

[INFO] Single-issue invocation unchangedidd-implement #19 path: Step 0.5 bash (108-144) untouched. Preface at line 18 of pr-flow.md is a no-op for N_ISSUES = 1. Confirmed backward compatible.

Recommendation

Merge as doc-only, then immediately file a follow-up issue to wire the cluster carve-out into idd-implement/SKILL.md:108-144 Step 0.5 bash (and the algorithm summary at 99-106). Until that ships, the documentation describes a contract the implementation does not honor — exactly the failure shape #96 was filed to prevent, just shifted one layer. Without that follow-up, this PR closes #96's documentation gap but leaves the behavioral gap open.

Alternative: expand this PR before merge to add the bash + summary updates, closing #96 in one shot.


Regression review · 1 of 6-AI verify pool · doc + cross-file consistency lens

@kiki830621
Copy link
Copy Markdown
Contributor Author

Codex review (PR #99 / #96)

Verdict: CONDITIONAL PASS

Note: posted on behalf of Codex CLI agent — the agent completed the review but could not post due to network error reaching api.github.com. Aggregator (Claude main thread) is posting verbatim.

Findings

  • HIGH — Doc/code gap: pr-flow.md (new ### Cluster mode override subsection) prescribes that Step 0.5 SHALL print a cluster-mode override notice when --no-pr/pr_policy=never is detected in cluster mode, but idd-implement/SKILL.md lines 108-144 (Step 0.5) contain no cluster-mode detection and no override notice. A reader following the SKILL.md bash verbatim will silently diverge from the spec. The Implementation Plan explicitly deferred this to a follow-up, which is acceptable only if a tracking issue is opened before merge — the PR body does not currently reference one.

  • MED — Anchor integrity: The heading added to pr-flow.md is ### Cluster mode override which GitHub renders as #cluster-mode-override. All three cross-references in batch-and-cluster.md and idd-implement/SKILL.md point to #cluster-mode-override — anchors match. However, the rationale phrase from batch-and-cluster.md line ~133 ("defensive: cluster on direct-commit = stacked half-isolated changes on default branch") does not appear verbatim in pr-flow.md. The new section captures the intent but the original wording is not preserved; if any downstream tool parses that exact phrase, it will break.

  • LOW — Backward compat: Single-issue idd-implement #19 flow is unaffected. The new section explicitly scopes itself to cluster mode; no existing Step 0 or Step 1 logic is touched by this diff. pr_policy defaults remain unchanged.

  • LOW — Language clarity: pr-flow.md new section uses "forces PR path" language but does not explicitly distinguish whether the override is hard (blocks direct-commit even on user demand) or soft (notice only, still proceeds direct-commit). Recommend an explicit "no abort, no silent ignore — proceeds as PR" line which IS present, so this LOW is partially resolved by the existing wording.

Recommendation

CONDITIONAL PASS. Before merging:

  1. Required: open a follow-up tracking issue for "implement cluster-mode override notice in SKILL.md Step 0.5" (the actual bash impl) and reference it in the PR description, OR extend this PR to include the ~15-line bash change.
  2. Optional: clarify hard-vs-soft override semantics in pr-flow.md (existing "no abort, no silent ignore" line largely covers this).

The anchor cross-references are correct; the rationale-preservation concern is minor and does not block merge.

@kiki830621
Copy link
Copy Markdown
Contributor Author

/idd-verify --pr 99 — Round 1 (#96)

Aggregate verdict: 🟡 CONDITIONAL PASS — 5/6 reviewers; 1 explicit APPROVE (Security). 4 of 5 substantive reviewers converged on the same HIGH finding (doc/code gap); fix path depends on whether R2 extends scope to add bash impl or files follow-up.

6-AI verdict

Reviewer R1 verdict Top finding
Requirements CONDITIONAL PASS L1 + L3 fully addressed; L2 (silent override removal) only partially — spec adds the override notice but bash doesn't emit it
Logic PASS w/ non-blocking findings HIGH: code/doc divergence (spec ahead of impl); MED: fork+cluster co-occurrence undefined; MED: notice format not perfectly parallel to fork's
Security APPROVE (no concerns) Clean doc-only PR. ⚠ Note: agent claimed "override behaviour was already implemented in Phase 0.5" — empirically wrong (Step 0.5 bash lines 108-144 have no cluster detection). Verdict still valid for security dimension (no exec surface change), but the supporting claim is incorrect
Regression PASS WITH FINDINGS HIGH: doc-ahead-of-code — same gap as Requirements/Logic; MED: SKILL.md:99-106 local algorithm summary now stale vs canonical pr-flow.md:18 preface
Devil's Advocate CONDITIONAL PASS (barely) Strongest objection: shipping a spec for a notice the code can't emit is arguably worse than the original 3-file contradiction — #96's L2 symptom (silent override) survives byte-for-byte while the canonical doc now promises a notice
Codex (gpt-5.5 xhigh) CONDITIONAL PASS HIGH: same doc/code gap; required action: either extend PR with ~15-line bash OR file follow-up before merge

Convergence map

Finding category Requirements Logic Security Regression DA Codex Count
HIGH — doc/code gap (Step 0.5 bash has no cluster detection) ✅ partial ❌ (claim wrong) 5/6
MED — fork+cluster precedence undefined 1/6
MED — notice format not fully parallel 1/6
MED — Step 0.5 local algorithm summary stale 1/6
MED — rationale phrase not preserved verbatim 1/6
LOW — hard-vs-soft override semantics 1/6
LOW — edge cases (duplicate #N, --pr+--no-pr collision) 1/6
LOW — anchor manipulation doc-rot risk 1/6

R1 — R2 decision required

The HIGH finding (5/6 convergent) is genuinely blocking by IDD standards: the spec describes Phase 0.5 behavior that the bash doesn't honor, so #96's stated "Expected" (observable parity with fork detection) is not yet met. Three R2 paths:

Path Effort Trade-off
(a) Extend scope: add bash impl in this PR + re-verify ~15 lines bash in idd-implement/SKILL.md Step 0.5 + R2 verify Closes gap entirely; matches feedback_verify_fix_same_pr user pref; minor scope creep from "doc-only" Implementation Plan
(b) Downgrade spec wording + file follow-up issue ~3 lines in pr-flow.md + 1 follow-up issue Honest about gap; keeps PR doc-only; spec language becomes "target state not yet implemented" instead of "current behavior"
(c) Merge as-is + file follow-up issue (Codex's path) 1 follow-up issue ref in PR body Minimal; accepts doc-ahead-of-code temporarily; relies on follow-up discipline to close gap

User-facing decision dispatched in main thread.

Secondary findings (R2 will address regardless of path)

  • Logic MED 1 — fork+cluster co-occurrence: clarify in pr-flow.md new subsection (one sentence: "If repo is both a fork AND cluster mode is invoked, both notices print; PR path is enforced regardless of which override fired first.")
  • Logic MED 2 — notice format parity: align with fork's pattern (→ cluster mode (N issues) → PR path enforced (overriding ...) is close but consider trailing punctuation match)
  • Regression MEDSKILL.md:99-106 Step 0.5 local algorithm summary doesn't mention cluster preface: add one-line note pointing to pr-flow.md § Cluster mode override
  • Codex MED — rationale phrase: optionally inline the "defensive: cluster on direct-commit = stacked half-isolated changes on default branch" sentence in pr-flow.md new section for downstream-grep stability

Per-reviewer comments


Next: R2 path selection (a/b/c above).

…0.5 bash (Refs #96)

R1 6-AI verify (5/6 convergent HIGH): R1 doc-only spec'd a Phase 0.5
cluster override notice that the actual bash had no capability to
emit (lines 108-144 had zero cluster detection). The L2 symptom #96
was filed to fix (silent override) survived byte-for-byte while the
canonical doc started promising a notice — arguably worse than the
original 3-file contradiction.

R2 closes the gap by extending PR scope (Implementation Plan listed
bash impl as out-of-scope "if necessary"; verify made it necessary).
User opt-in via AskUserQuestion (option a: extend scope + R2 verify).

idd-implement/SKILL.md Step 0.5 (~24 new lines):
- Parse #N tokens in $@, set ISSUE_COUNT, derive CLUSTER_MODE=true
  if ≥2
- Pre-empt the resolution table: if CLUSTER_MODE → PATH_CHOICE="pr"
  unconditionally; on --no-pr or pr_policy=never collision, print
  `→ cluster mode (N issues) → PR path enforced (overriding ...)`
- If fork ALSO detected (independent pre-emption), print fork notice
  too — both pre-emptions reach same destination (PR), each announces
  its own reason
- Local algorithm summary (lines 99-106) gets new row 0 noting
  cluster pre-emption (closes Regression MED finding about stale
  local summary vs canonical pr-flow.md preface)

pr-flow.md § Cluster mode override:
- Inline rationale phrase "stacked half-isolated changes on default
  branch" verbatim (closes Codex MED about downstream-grep stability)
- Add explicit "Fork + cluster co-occurrence" paragraph: both
  pre-emptions independently force PR; both notices print; no
  precedence question (closes Logic MED 1)

Behavioral verification (8-case dry-run with mocked gh/jq):
- T1: single issue, no flag → ask path (no cluster, backward compat ✓)
- T2: cluster (3 #N), no flag → PR path, no notice ✓
- T3: cluster + --no-pr → "...(overriding --no-pr)" + PR ✓
- T4: cluster + --pr → PR, no notice (explicit, no collision) ✓
- T5: cluster + pr_policy=never → "...(overriding pr_policy=never)" ✓
- T6: cluster + --no-pr + never → "...(overriding --no-pr / pr_policy=never)" ✓
- T7: cluster + fork + --no-pr → cluster notice AND fork notice ✓
- T8: single + --no-pr → no-pr path (backward compat ✓)

`bash -n` clean.

R1 master verify: #99 (comment)
@kiki830621
Copy link
Copy Markdown
Contributor Author

Security review R2 (PR #99 / #96)

Verdict: APPROVE

R1 factual error — acknowledged

My R1 review (comment 4483939943) stated cluster override "was already implemented in Phase 0.5; this PR just documents existing reality." That was empirically wrong — the R1 bash (then lines 108–144) had zero cluster detection, as the convergent HIGH from four other reviewers correctly established. R2 (5351116) is the actual implementation. The R1 verdict's security conclusion (no concerns for a doc-only change) was harmless given the doc-only diff, but the reasoning was unfounded. Correcting the record here.

R2 evaluation (~24 new lines of executable bash, Step 0.5)

  1. Arithmetic injection — refuted. ISSUE_COUNT=$((ISSUE_COUNT + 1)) evaluates only hardcoded operands; the user-controlled $arg never enters the $(( )) context. It is matched by the case glob \#[0-9]* (a pattern test, not an eval) and then discarded — the body increments a fixed counter. An arg like #42; rm -rf / would match the glob and still only do ISSUE_COUNT+1; the ; and rest are inert text. No injection path.

  2. OVERRIDE_SRC interpolation — safe. The variable is assembled exclusively from string literals --no-pr and pr_policy=never (gated by $PR_FLAG/$PR_POLICY equality tests). No user-supplied content reaches the echo. $ISSUE_COUNT is the only other interpolated value and is a pure integer. Worst case is a benign integer/literal in stdout.

  3. Auto-close trap scan — clean. Grepped the full R2 diff content and the commit message body for Closes #<digit> / Fixes #<digit> / Resolves #<digit>: zero matches. The new SKILL.md line 100 uses the safe abstract token #N (no digit). pr-flow.md prose says "#N arguments" abstractly. No squash-merge auto-close risk introduced.

  4. No new external exec paths. The bash reuses the pre-existing gh repo view and jq calls (already present pre-R2, mocked in the 8-case dry-run). No new commands, subshells consuming untrusted input, eval, or curl.

bash -n clean per commit message; logic confined to local variable assignment and echo. Security surface expansion is negligible. No CRITICAL/HIGH/MEDIUM findings.

@kiki830621
Copy link
Copy Markdown
Contributor Author

Requirements review R2 (PR #99 / #96)

Verdict: PASS

R2 commit 5351116 closes the one CONDITIONAL finding from R1. The L2 doc/code gap — spec promised an override notice the bash had no capability to emit — is now fully wired.

R1 → R2 closure table

R1 finding R2 status Evidence
MEDIUM (CONDITIONAL) — L2 spec/code gap: override notice spec'd in pr-flow.md + SKILL.md but Step 0.5 bash had zero cluster detection, so idd-implement #34 #36 --no-pr still silently overrode at runtime CLOSED Step 0.5 bash now parses \#[0-9]* tokens → ISSUE_COUNT, derives CLUSTER_MODE="true" at ≥2. A new if [ "$CLUSTER_MODE" = "true" ] branch sits first, pre-empting the --pr/--no-pr/IS_FORK/PR_POLICY table, and echos the notice on a --no-pr / pr_policy=never collision.
LOW — scope discipline Held R2 touches only the 2 files needed; no scope creep.
POSITIVE — backward compat Held Rows 1–6 byte-identical; cluster branch is additive elif-prepended-as-if.

Evaluation against the 5 R2 checkpoints

  1. Cluster detection added — ✅ ISSUE_COUNT counter + CLUSTER_MODE derivation present (SKILL.md Step 0.5, lines 111–123).
  2. Spec'd notice printed — ✅ Emits → cluster mode ($ISSUE_COUNT issues) → PR path enforced (overriding $OVERRIDE_SRC); OVERRIDE_SRC composes to --no-pr, pr_policy=never, or --no-pr / pr_policy=never — matches pr-flow.md:55 byte-for-byte.
  3. Ordering correct — ✅ Cluster branch is the leading if; all flag/fork/policy branches demoted to elif. Pre-emption semantics match pr-flow.md "precondition that pre-empts the Resolution algorithm".
  4. Single-issue backward compat — ✅ Dry-run T1 (#19, no flag) → ask path unchanged; T8 (#19 --no-pr) → no-pr path unchanged. Cluster branch is inert at ISSUE_COUNT < 2.
  5. Coverage matrix — ✅ L1 (canonical table carve-out), L2 (notice now emitted at runtime), L3 (--no-pr+cluster → proceed-as-PR-with-notice, no abort/silent) all fully covered. The R1 "partial L2" downgrade is resolved.

Independent verification

  • bash -n on the isolated Step 0.5 block — clean.
  • 8-case functional dry-run (mocked args/policy/fork) — all pass:
    • T3 cluster + --no-proverriding --no-pr
    • T5 cluster + pr_policy=neveroverriding pr_policy=never
    • T6 cluster + --no-pr + neveroverriding --no-pr / pr_policy=never
    • T7 cluster + fork + --no-pr → cluster notice then fork notice (both pre-emptions announce; pr-flow.md "Fork + cluster co-occurrence" paragraph documents this)
    • T2 cluster, no flag → PR, no notice (correct — no collision)
    • T4 cluster + --pr → PR, no notice (explicit, no collision)

Remaining findings

None blocking. One observation (non-blocking, NIT): the \#[0-9]* glob counts any #-prefixed numeric token in $@; a stray literal like #5 inside an unrelated arg could over-count. In practice idd-implement's arg surface is #N issue refs + --flags only, so the risk is theoretical. No action required.

#96's Expected section ("single, documented, behaviorally explicit contract; every override prints an explicit notice; --no-pr+cluster is a single specified behavior") is now satisfied in both the canonical doc and the executable path. Recommend merge.

@kiki830621
Copy link
Copy Markdown
Contributor Author

Regression review R2 (PR #99 / #96)

Reviewer: Regression (1 of 6-AI verify pool) · R2 of commit 5351116
R1 verdict: PASS WITH FINDINGS (comment 4483946051) — 1 HIGH + 1 MED.
Method: walked post-R2 bash (SKILL.md:110-161), CRLF-stripped bash -n (clean), 15-case behavioral trace with mocked flags/policy, full-repo anchor + verbatim-quote sweep.

Verdict: PASS — both R1 findings closed, no regression

R1 → R2 closure table

R1 finding Sev R2 evidence Status
Doc claims override notice the bash cannot emit HIGH SKILL.md:111-141 now parses \#[0-9]*ISSUE_COUNT, derives CLUSTER_MODE, pre-empts the if-chain with PATH_CHOICE="pr" + OVERRIDE_SRC echo. Doc promise = code behavior. Verified by trace T3/T5/T6. CLOSED
Step 0.5 numbered summary stale (no cluster preface) MED SKILL.md:100-101 adds row 0. Cluster mode (≥2 #N args) → pre-empts entire table; PR path forced. Exactly the row 0 R1 recommended. CLOSED

Verification results

1. HIGH closure — Confirmed. Cluster detection (for-loop \#[0-9]* arm + ISSUE_COUNT≥2CLUSTER_MODE) and override notice (OVERRIDE_SRC accumulation + echo) are both present and reach the same PATH_CHOICE="pr" destination as the fork branch. Mirrors fork pattern faithfully.

2. MED closure — Confirmed. Row 0 present at SKILL.md:100, anchored to pr-flow.md § Cluster mode override.

3. Single-issue backward compatNo regression. Trace #19: ISSUE_COUNT=1, CLUSTER_MODE="false", the if [ "$CLUSTER_MODE" = "true" ] branch is skipped, control falls through to the unchanged elif --pr / --no-pr / fork / always / never / ask chain. All five single-issue traces (#19, --no-pr, --pr, pr_policy=never, IS_FORK=true) produce byte-identical output to pre-R2. The for-loop only adds a counter; the --pr/--no-pr case arms are semantically identical (whitespace-only diff). No scenario changes single-issue behavior.

4. --in-chain interaction — Confirmed correct. --in-chain matches none of --pr / --no-pr / \#[0-9]*, so the for-loop silently ignores it; ISSUE_COUNT unaffected. idd-all-chain recursive --in-chain single-root calls keep their existing resolution. Right behavior.

5. Cross-reference integrity — Confirmed. ### Cluster mode override → GitHub slug cluster-mode-override; all 3 cross-refs (pr-flow.md:18, batch-and-cluster.md:133, SKILL.md:49) use the exact slug. Rationale phrase "stacked half-isolated changes on default branch" now inlined verbatim in pr-flow.md:50 per Codex MED — and batch-and-cluster.md:133 no longer carries the orphaned copy. Repo-wide sweep: no stale verbatim quotes outside diff'd files.

6. Test coverage — 8 cases are well-chosen (single/cluster × flag/policy/fork matrix, both backward-compat anchors T1/T8). One gap, INFO only: --pr + --no-pr both set is untested. Trace shows last-wins (pre-existing case-statement behavior, not introduced by R2 — not a regression). #abc malformed token: \#[0-9]* correctly requires a digit, so #abcISSUE_COUNT unincremented (verified) — safe by construction, untested but low-risk.

Remaining findings

[INFO] Cluster + --pr + --no-pr (no-pr last): cluster pre-empts to PR correctly, but notice prints overriding --no-pr while --pr was also passed — cosmetically the override "source" is debatable. Destination is correct; purely a message nicety. No action required.

[INFO] SKILL.md retains pre-existing CRLF line terminators (predates R2 — HEAD~1 also CRLF). Not a regression; flagging only as latent hygiene.

No blocking findings. R2 closes #96's doc-and-code gap in one shot; single-issue path provably unchanged.


Regression review R2 · 1 of 6-AI verify pool · backward-compat + cross-file lens

@kiki830621
Copy link
Copy Markdown
Contributor Author

Logic review R2 (PR #99 / #96)

Verdict: PASS

R2 (5351116) closes the R1 Logic HIGH and both MEDs. Bash impl now matches spec; new logic is internally consistent.

R1 → R2 closure table

R1 finding Sev R2 status Evidence
Code/doc divergence — notice spec'd, bash had no cluster detection HIGH CLOSED Step 0.5 bash now parses #N tokens (ISSUE_COUNT), derives CLUSTER_MODE, pre-empts the resolution if/elif chain as the first branch (SKILL.md:118–141). Doc and code now agree.
Fork + cluster co-occurrence undefined MED 1 CLOSED pr-flow.md:60 adds explicit "Fork + cluster co-occurrence" paragraph; bash prints fork notice after cluster notice when IS_FORK=true (SKILL.md:141). Both reach PR path — no precedence conflict.
Notice format not parallel; parenthetical lists both conditions unconditionally MED 2 CLOSED (improved beyond ask) OVERRIDE_SRC is now accumulated — cites only the actual triggering condition(s), not both unconditionally. Fork notice was harmonized to → Repo is a fork; PR path enforced. (arrow prefix added) — both notices now arrow-prefixed and parallel.

Walk-through (verifies internal consistency)

  • if/elif chain (Q1): CLUSTER_MODE=true is the first branch, unconditionally sets PATH_CHOICE="pr"; all later elif arms (--pr/--no-pr/fork/pr_policy/ask) are correctly skipped. Pre-empt semantics match pr-flow.md.
  • OVERRIDE_SRC accumulation (Q4): (a) --no-pr alone → "--no-pr"; (b) pr_policy=never alone → :+ guard yields "pr_policy=never"; (c) both → "--no-pr / pr_policy=never"; (d) neither → empty → no echo. All four branches correct.
  • Cluster + --pr (T4): no collision, OVERRIDE_SRC stays empty, silent — correct (explicit intent, nothing to override).
  • --in-chain (Q5): matches no case arm → ISSUE_COUNT untouched. idd-all-chain context safe. ✓
  • Anchor (Q6): ### Cluster mode override#cluster-mode-override. All three referrers (pr-flow.md:18, batch-and-cluster.md:133, SKILL.md:49,101,130) resolve. ✓

New R2 findings (all non-blocking)

  • 🟡 LOW — glob looser than canonical regex. Bash uses \#[0-9]*; batch-and-cluster.md:47 declares the canonical parse rule as ^#\d+$ (anchored). #42abc is counted by the bash glob but rejected by the documented regex — a minor code/doc inconsistency. Also #42abc as a cluster-count false-positive is theoretically possible, though no realistic IDD invocation produces such tokens. --issue=#42 (false negative) is not a supported syntax, so harmless. Recommend a follow-up to tighten the glob toward \#[0-9]*[!a-zA-Z] or note the intentional looseness.
  • 🟢 LOW (clean) — duplicate #34 #34 still counts as 2 (no de-dup); pre-existing from R1 LOW, not regressed by R2, out of this PR's scope.

Recommendation

Merge-eligible. R1 HIGH + both MEDs closed; MED 2 was closed better than the R1 recommendation (conditional accumulation vs. fixed string). The single new LOW is a doc-vs-glob nit deferrable to a follow-up.

@kiki830621
Copy link
Copy Markdown
Contributor Author

Devil's Advocate review R2 (PR #99 / #96)

Verdict: CONDITIONAL PASS — R2 genuinely closes the R1 strongest objection (no longer theater), but Objection 2 from R1 survives untouched and the PR now over-claims one thing it does not deliver. Honest framing: merge-eligible, but the design tension is being papered over a second time.

Objection 1 (was STRONG, now WITHDRAWN) — the bash impl is real, not theater

I attacked this hard expecting "moved the spec from one section to another." It is not that. R2 (5351116) adds genuine executable logic to Step 0.5: a for-loop counts \#[0-9]* tokens into ISSUE_COUNT, derives CLUSTER_MODE, and inserts a leading if branch that pre-empts the entire --pr/--no-pr/fork/pr_policy chain, emitting the spec'd notice on a --no-pr/pr_policy=never collision. Yes, SKILL.md is prose Claude executes — but that is true of every bash block in every IDD skill, including the fork-detection branch that has shipped for 30+ versions. The R1 gap was not "prose vs compiled" — it was that the prose literally had no cluster branch at all. R2 adds the branch. The bash is now the executable contract, parallel to fork detection. Materially different from R1. Objection withdrawn.

Objection 2 (STRONG — UNRESOLVED, this is now my strongest) — Option A still papers over the feature-branch tension

My R1 objection stands verbatim and R2 added nothing to address it. R2 made the forced behavior more thoroughly enforced (now actually wired) without touching the legitimacy question the diagnosis itself raised: cluster + direct-commit on a feature branch idd/foo-baz is N Refs #N commits on that branch — not "stacked half-isolated changes on default branch." R2's pr-flow.md:50 inlines that exact rationale phrase verbatim — cementing a rationale the diagnosis explicitly called「被誇大」(exaggerated). The bash unconditionally sets PATH_CHOICE="pr" with zero branch-context check (git branch --show-current vs default). A user already on a feature branch, running cluster + --no-pr, gets a forced PR and a one-line notice that does not answer "why, I'm not on default?" R2 is a faithful, well-tested implementation of a design the diagnosis flagged as half-wrong. #96 will likely re-open. Not a blocker for this PR (Option A was the user's explicit choice), but the convergent 6-AI "PASS" obscures that the conceptual defect is now harder to dislodge because it has executable + documented + tested inertia.

Objection 3 (MEDIUM — UNRESOLVED) — the notice is still too quiet for a discretionary override

One line, no color, no separator, same stdout stream. R2 did harmonize the fork notice to → Repo is a fork; PR path enforced. (arrow added) — cosmetic parity. But fork-PR is a technical necessity; cluster-PR is a design preference the diagnosis admits is exaggerated. A pr_policy:"never" user scrolls past this in milliseconds. "We echoed it in scrollback" remains weak recourse for overriding a config the user deliberately set. Deferred, not blocking — but real.

Objection 4 (NEW, MEDIUM) — pr-flow.md over-claims idd-verify / idd-close

pr-flow.md says cluster mode applies to "idd-implement, idd-verify, or idd-close invoked with ≥2 #N". R2 wired the bash only into idd-implement Step 0.5. I checked: idd-verify Step 0.5 resolves --pr/--commits/--branch/--since (an input source, not a PR-vs-direct-commit path — no pr_policy, no isFork); idd-close Step 1.5 only checks for unmerged PRs. Neither resolves PR-vs-direct-commit at all — so neither needs cluster pre-emption, and that is fine. But the canonical doc's "forces PR path" sentence enumerating all three implies all three do path resolution. They don't. The sentence is harmless-but-misleading: the only skill where "cluster forces PR" is a decision is idd-implement; for verify/close a PR already exists by construction. Recommend a half-sentence clarifying that verify/close inherit the cluster-PR (a PR exists) rather than resolve it.

Objection 5 (LOW — confirmed weak, as Logic/Requirements flagged) — #[0-9]* glob is loose

Verified by direct test: #42abc → counted (glob is unanchored, canonical regex ^#\d+$ would reject); 34 (no #) → not counted; #34 #34 duplicate → counts as 2 (no de-dup → #34 #34 wrongly trips cluster). All real, all theoretical for idd-implement's actual arg surface (#N + --flags). Non-blocking; a follow-up nit.

Recommendation

CONDITIONAL PASS → MERGE eligible. R2 honestly closes the R1 blocking HIGH — the bash is real. Objections 2/3 are the design tension Option A chose not to resolve; the user owns that choice and the diagnosis predated it, so they are not merge blockers — but they SHOULD be filed as a follow-up issue before merge so the "Option A perpetuates an exaggerated rationale" finding does not drift. Objection 4 (verify/close over-claim) is a 1-sentence doc fix worth doing in this PR. Objection 5 is a deferrable nit.

MERGE — conditional on (a) one-sentence pr-flow.md clarification that verify/close inherit rather than resolve the cluster-PR path, and (b) a follow-up issue capturing the feature-branch-cluster-direct-commit legitimate-workflow tension (Objection 2). If the user declines (a), downgrade to PASS-with-debt and still file (b).

@kiki830621
Copy link
Copy Markdown
Contributor Author

Codex review R2 (PR #99 / #96)

Verdict: PASS

Posted on behalf of Codex CLI agent — review completed but comment posting failed (network error reaching api.github.com). Aggregator (Claude main thread) posting verbatim.

R1 → R2 closure

  • R1 HIGH (doc/code gap) → CLOSEDSKILL.md lines 111-141 now contain explicit cluster detection: a for arg in "$@" loop with case "$arg" in \#[0-9]*) increments ISSUE_COUNT, followed by [ "$ISSUE_COUNT" -ge 2 ] setting CLUSTER_MODE, a pre-empt if block that prints the override notice, and OVERRIDE_SRC accumulation. The bash matches the Phase 0.5 spec in pr-flow.md.
  • R1 MED (rationale phrase) → CLOSED — exact phrase "stacked half-isolated changes on default branch" appears at pr-flow.md line 50.

New R2 findings

  • LOWSKILL.md glob \#[0-9]* matches #42abc and #42-foo (anything with a digit after #). A duplicate arg like #42 #42 counts as 2, incorrectly triggering CLUSTER_MODE. batch-and-cluster.md:47 uses the stricter ^#\d+$ pattern; the bash glob is less precise. Recommend tightening or documenting the permissive behavior explicitly.
  • LOW (resolved on inspection)${OVERRIDE_SRC:+$OVERRIDE_SRC / } parameter expansion is syntactically correct and safe; no trailing-slash bug.
  • INFO — Single-issue path (idd-implement #19): ISSUE_COUNT=1, CLUSTER_MODE stays false, pre-empt block skipped entirely. Backward compat confirmed.

Recommendation

MERGE — R1 HIGH is closed and the logic is functionally correct. The #42abc false-positive on cluster count is a hardening note, not a correctness blocker for the stated feature. File a follow-up issue if stricter glob validation is desired.

…ment only (Refs #96)

R2 verify Devil's Advocate (Objection 4, empirically verified): the
§ Cluster mode override opening sentence claimed cluster mode for
`idd-verify` / `idd-close` "pre-empts the Resolution algorithm" — but
those skills never run path resolution. `idd-verify` resolves an input
source; `idd-close` checks for unmerged PRs. Only `idd-implement`
resolves PR-vs-direct-commit path. The original wording was a
self-contradicting over-claim (a skill can't pre-empt an algorithm it
never runs).

Fix: split the sentence — cluster mode is a multi-issue mode for all
three skills (shared branch + PR), but **path resolution is
idd-implement's job**. idd-verify / idd-close are cluster-aware yet
operate on the cluster's already-existing PR — they consume the path
decision, they don't make it.

Doc-only wording clarification; no logic/behavior change. DA
pre-specified this exact fix shape ("conditional on a 1-sentence
pr-flow.md verify/close clarification") and recommended MERGE.

R2 master verify: #99 (Round 2, 6/6)
@kiki830621
Copy link
Copy Markdown
Contributor Author

/idd-verify --pr 99 — Round 2 (#96)

Aggregate verdict: ✅ PASS — 6/6 reviewers. R1's convergent HIGH (doc/code gap) closed by R2 commit 5351116. Devil's Advocate's one new actionable finding closed by R3 commit 04c51cb. Ready to merge.

R2 (commit 5351116) extended PR scope per user opt-in (R1 AskUserQuestion option a): added the cluster-detection bash to idd-implement Step 0.5 that R1's doc-only spec promised but couldn't emit.

6-AI verdict (R2)

Reviewer R2 verdict Note
Requirements PASS R1 CONDITIONAL fully closed; #96 L1/L2/L3 all covered; independently re-ran 8-case dry-run
Logic PASS All 3 R1 findings closed; OVERRIDE_SRC 4-case correctness verified; 1 new LOW (glob)
Security APPROVE New bash audited — no arith injection, no interpolation leak; R1 factual error acknowledged (had wrongly claimed override "already implemented")
Regression PASS Both R1 findings closed; single-issue backward compat traced; --in-chain correctly ignored; 2 INFO
Devil's Advocate CONDITIONAL PASS → MERGE Objection 1 (R1's strongest) withdrawn — R2 bash is real, not theater. Objection 4 (new, actionable) + Objection 2 (non-blocking) — see below
Codex (gpt-5.5 xhigh) PASS / MERGE R1 HIGH + MED both closed; 1 LOW (glob) — "not a correctness blocker"

R1 → R2 finding closure

R1 finding Severity R2 status
HIGH — doc/code gap (Step 0.5 bash had no cluster detection) HIGH CLOSED — R2 added ISSUE_COUNT parse + CLUSTER_MODE derivation + pre-empt block + OVERRIDE_SRC accumulation; 5/6 R2 reviewers independently confirmed
MED — fork+cluster precedence undefined (Logic) MED CLOSED — pr-flow.md "Fork + cluster co-occurrence" paragraph; bash prints both notices
MED — notice format not parallel (Logic) MED CLOSEDOVERRIDE_SRC cites only actual trigger(s); fork notice harmonized
MED — Step 0.5 local algorithm summary stale (Regression) MED CLOSED — new row 0. Cluster mode (≥2 #N args) added
MED — rationale phrase not verbatim (Codex) MED CLOSED — "stacked half-isolated changes on default branch" inlined at pr-flow.md:50
Security R1 factual error ("already implemented") ACKNOWLEDGED by Security R2

R2 new finding → R3 closure

R2 finding Source Severity Disposition
Objection 4 — pr-flow.md over-claimed cluster mode "pre-empts the Resolution algorithm" for idd-verify/idd-close (those skills never run path resolution) Devil's Advocate actionable (DA-specified fix) CLOSED in R3 (04c51cb) — opening sentence split: path-resolution pre-emption is idd-implement-only; verify/close are cluster-aware but consume the path, don't resolve it
Objection 2 — Option A forces PR even on a non-default feature branch where cluster direct-commit is legitimate Devil's Advocate (R1+R2) non-blocking Filed → #100 (Option B revisit candidate, branch-context-gated)
LOW — \#[0-9]* glob over-counts #42abc / duplicate #34 #34 Logic + Codex LOW, "deferrable" per both finders Filed → #100 (Finding 2)
INFO ×2 — --pr+--no-pr collision untested (pre-existing last-wins); SKILL.md pre-existing CRLF Regression INFO ACKNOWLEDGED — not introduced by #99

Why R3 has no separate verify round

R3 (04c51cb) is a 1-sentence doc wording clarification that Devil's Advocate itself specified ("conditional on a 1-sentence pr-flow.md verify/close clarification") and recommended MERGE around. No logic/behavior change, no new surface — re-running a 6-AI ensemble for the finder's own pre-approved wording fix would be pure ceremony.

Verify-fix convergence (R1 → R2 → R3)

Same-PR fix per feedback_verify_fix_same_pr user preference — verify findings fixed to clean before merge, not deferred to post-merge follow-ups (except the 2 genuinely non-blocking items, which #100 tracks).

Dogfood-the-fix

The new cluster-detection bash, run against this very PR's invocation history: /idd-all 96 is single-issue (ISSUE_COUNT=1) → CLUSTER_MODE=false → pre-empt block skipped → existing resolution path → (PR, unattended) resolved exactly as before. Backward compat holds on the PR that adds the cluster carve-out.

Per-reviewer R2 comments


Next: human review of PR #99 → merge → /idd-close #96. Follow-up #100 tracks the 2 non-blocking deferred items.

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