Skip to content

fix: spectra-archive-post-ic linked-issue escape hatch + prose detection (#170)#171

Merged
kiki830621 merged 2 commits into
mainfrom
idd/170-post-ic-linked-issue
May 31, 2026
Merged

fix: spectra-archive-post-ic linked-issue escape hatch + prose detection (#170)#171
kiki830621 merged 2 commits into
mainfrom
idd/170-post-ic-linked-issue

Conversation

@kiki830621
Copy link
Copy Markdown
Contributor

@kiki830621 kiki830621 commented May 31, 2026

Refs #170

Summary

Fixes the spectra-archive-post-ic.sh double-failure surfaced when archiving #167: detection missed the prose-only issue #N reference AND --linked-issue rejected on an empty candidate set — so both the auto-detector and its manual override failed together exactly when the fallback was needed (#167's Implementation Complete had to be posted by hand).

  • Escape hatch restored: --linked-issue membership validation now only runs when detection found candidates (the disambiguation case); an empty set treats the explicit override as authoritative.
  • Wider detection: fallback 2 regex extended to match the IDD-prose issue #N form that /spectra-propose writes, not just Refs / Closes / Fixes trailers.

Checklist

  • Diagnose (Simple)
  • Implement (1 commit, TDD)
  • Verify (6-AI on this PR)
  • Verify-gated: after merge, run the idd-close skill manually on the issue (enforces gate + closing summary). Do NOT add an auto-close trailer.

Test plan

  • bash .claude/scripts/tests/spectra-archive-post-ic/test.sh → 13/13 PASS (2 new fixtures + 11 existing).

…ion (#170)

The --linked-issue override validated membership against the detected
candidate set even when that set was EMPTY, so when detection found
nothing the explicit override was rejected too — both failure modes fired
together exactly when the fallback was needed (#167's IC had to be posted
manually). Now the membership check applies only when candidates were
actually detected; an empty set treats --linked-issue as the authoritative
escape hatch. Integer validation reordered first (emit_outcome exits).

Also widen detection fallback 2 to match the IDD-prose form "issue #N"
(what /spectra-propose writes in tasks.md), not just Refs/Closes/Fixes.

Tests: +2 fixtures (12 prose-issue detection, 13 empty-candidate override);
11 existing still pass (fixture 09 stays rejected on its non-empty set).

Refs #170
@kiki830621
Copy link
Copy Markdown
Contributor Author

Verify Report — PR #171 (#170)

Engine

5 general-purpose Agents (Requirements / Logic / Security / Regression / Devil's Advocate) + Codex (gpt-5.5, xhigh). Test suite re-run independently by 3 reviewers + Codex: 13/13 PASS.

Aggregate

PASS — 0 hard-blocking. The core #170 fix (empty-set escape hatch + integer-first reorder) is confirmed correct by all 6: emit_outcome exits unconditionally (reorder valid), the [ -n "$CANDIDATES" ] guard is load-bearing (empty set would else false-fail), fixture 09's reject contract is byte-for-byte preserved, no injection surface, scope clean.

Findings (merged across 6 sources)

# Sev Finding Source Action
1 P2 F2 regex [Ii]ssue #N is unanchored: reissue #5/tissue #9 substring-match (LOW); and cross-reference prose (see issue #164, 可能 issue #46) becomes a spurious candidate. Codex's sharp point: a single spurious candidate makes the set non-empty → defeats the escape hatch (--linked-issue 555 rejected). Confirmed on a shipped archive (2026-05-10-add-multi-finding-source-mode{46,48}). codex + all 5 agents In-scope fix (word-boundary anchor)
2 P3 Override integer check ^[0-9]+$ allows 0, but the error message says "positive integer". --linked-issue 0 posts to /issues/0. codex In-scope fix (reject 0 → ^[1-9][0-9]*$)
3 MEDIUM Escape hatch is a net-new path where empty-set + --linked-issue <wrong-but-existing> silently posts the IC supersession anchor to an unrelated live issue (no existence/correctness guard). Coupled with #1, the membership-validation semantics conflate exit-75 disambiguation with user override. agents:devils-advocate + codex Follow-up (membership-semantics design)
4 LOW Fixture 13 passes only because the harness runs from /tmp (F3 git-log empty there). From the repo cwd, F3 finds the fixture's own #170 commit → candidate {170} → escape hatch not exercised (Codex reproduced). Production trigger (uncommitted archive at post-IC time) differs. codex + DA In-scope fix (document the coupling)
5 P3 emit_outcome returns exit 0 on failure messages (inconsistent with the "0 = success" header). codex By-design — best-effort per #56 (archive succeeded; IC post is convenience). No change.
6 trivial spectra-archive/SKILL.md says "All 11 fixtures pass" — now 13+ (this PR added 2). regression In-scope fix (count; this PR caused the drift)

Scope Check

Clean — diff touches only spectra-archive-post-ic.sh + fixtures 12/13. No scope creep.

Plan

Per same-PR-fix discipline: fixing #1 (word-boundary), #2 (reject 0), #4 (doc), #6 (count) in this PR + re-running the suite. #3 (the deeper membership-semantics conflation + wrong-existing mis-post) → follow-up issue. #5 accepted as by-design.

- Word-boundary anchor the fallback-2 regex `(^|[^[:alnum:]_])` so `[Ii]ssue`
  no longer substring-matches `reissue`/`tissue` (verify P2, 6/6 consensus).
  Codex's escalation: a spurious candidate flips the path off the escape hatch.
- Reject 0 in the --linked-issue integer check (`^[1-9][0-9]*$`) — matches the
  "positive integer" message; `0` would otherwise post to /issues/0 (codex P3).
- Document fixture 13's /tmp-cwd coupling: escape-hatch reachability is
  detection-emptiness-dependent; production posts the IC pre-commit so F3
  git-log sees an untracked archive path → empty (DA-3 / codex).
- SKILL.md fixture count 11 -> 14 in both mirrors (this PR added 3 fixtures).

Tests 13 -> 14 (word-boundary fixture). All GREEN. The deeper membership-
semantics design (spurious candidate defeats override; wrong-but-existing
silent mis-post) is tracked in #172.

Refs #170
@kiki830621
Copy link
Copy Markdown
Contributor Author

Verify findings resolved (commit 8db1423)

In-PR fixes for the 6-AI round:

# Sev Fix
1 P2 Word-boundary anchor (^|[^[:alnum:]_]) on the fallback-2 regex — reissue #5/tissue #9 no longer false-match. + fixture 14 asserting it.
2 P3 --linked-issue integer check tightened to ^[1-9][0-9]*$ — rejects 0 (was posting to /issues/0 despite the "positive integer" message).
4 LOW fixture 13 README.md documents the /tmp-cwd coupling (escape-hatch reachability is detection-emptiness-dependent; production posts IC pre-commit → F3 sees an untracked archive → empty).
6 trivial SKILL.md fixture count 11 → 14 (both mirrors).
3 MEDIUM Follow-up #172 — the deeper membership-semantics design (spurious candidate defeats override; wrong-but-existing silent mis-post). Beyond #170's reported scope.
5 P3 emit_outcome exit-0-on-failure — accepted as by-design (best-effort IC post per #56; archive itself already succeeded).

Tests: 13 → 14, all GREEN. bash -n clean. The core #170 double-failure (empty-set escape hatch + integer-first reorder) was confirmed correct by all 6 reviewers and is unchanged.

Phase: verified (no remaining blocking or in-PR findings; #172 tracks the design follow-up).

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