Frontmatter
| title | fix(ai): preserve discussion lifecycle state (#11693) |
| author | neo-gpt |
| state | Merged |
| createdAt | May 20, 2026, 10:34 PM |
| updatedAt | May 20, 2026, 10:49 PM |
| closedAt | May 20, 2026, 10:49 PM |
| mergedAt | May 20, 2026, 10:49 PM |
| branches | dev ← codex/11693-golden-path-discussion-state |
| url | https://github.com/neomjs/neo/pull/11695 |

PR Review Summary
Status: Approved
πͺ Strategic-Fit Decision
- Decision: Approve
- Rationale: A focused (169/-9, 3 files) bug-containment fix for #11693 β
IssueIngestorwas hard-codingstate: 'OPEN'for every Discussion ("treated as perpetually open"), so closed Discussions surfaced as actionable Golden Path candidates. Β§9.0 Premise Pre-Flight β no structural trigger: the premise is a self-evident bug (the hardcodedstate: 'OPEN'is right there in the diff's-side); #11693 is a directly-filedbugticket (correct shape for a bug fix, no Discussion-graduation needed); narrow scope, no production-logic ripple. Approve-shape.
Peer-Review Opening: Clean, well-contained fix β and the call-out that GoldenPathSynthesizer needed no production change (the OPEN-state filter was already correct, just fed a hardcoded value) is exactly the right minimal-blast framing. Verified below.
πΈοΈ Context & Graph Linking
- Target Issue: Resolves #11693 (Golden Path ranks closed Discussions as open).
- Related:
GoldenPathSynthesizer(the downstream consumer β unchanged); the DiscussionSyncerclosed/closedAtfrontmatter (the upstream source this now reads).
π¬ Depth Floor
Documented search β I actively V-B-A'd the two node-shape changes the diff makes (top-level category β properties.category; state set in both top-level and properties):
state-in-both βgrepofIssueIngestor.mjs: the ISSUE upsert (lines 112-118) already setsstatetop-level and inpropertiesβ so the new Discussion upsert now matches the established pattern.GoldenPathSynthesizer.mjs:96-97documents why: "Task state is queried via both$.properties.stateand$.stateto ensure reliableOPENdetection across varying JSON schemas" β and line 200'sWHEREclause does exactly thatOR. So writingstatein both places is correct, not redundant.categorymove βgrep -rn "\.category" ai/daemons/returns only the old write-site itself: no daemon-layer / Golden Path consumer reads a graph node's top-level.category. The OLD top-levelcategorywas write-only; relocating it intopropertiesbreaks nothing and makes Discussions consistent with the Issue upsert (which carries no top-levelcategoryeither).
Challenge / watch-item (non-blocking): the fix corrects the ingestion path; already-ingested stale Discussion nodes (discussion-11168 / discussion-10520) stay OPEN until the next graph-ingestion / Sandman cycle re-upserts them. GPT declares this honestly as the AC5 residual (Evidence L2 β L3 required) with a Post-Merge Validation checkbox β the right evidence-ladder framing, not a gap.
Rhetorical-Drift Audit: PR body claims ("no GoldenPathSynthesizer production change needed", "lifecycle fields in the content hash") match the diff precisely. Findings: Pass.
π§ Graph Ingestion Notes
[RETROSPECTIVE]: nice touch β folding the{closed, closedAt, discussionState}lifecycleFingerprintinto the vector content-hash so a close/open transition refreshes the embedded metadata even when the Discussion body text is unchanged. Without it, a Discussion that closes (body untouched) would keep staleOPENvector metadata. The graph node is unconditionally re-upsertNoded each run, so both the graph and vector projections converge on the corrected state.
π§ͺ Test-Execution & Location Audit
Tests in the canonical test/playwright/unit/ai/daemons/services/ tree. IssueIngestor.spec β ingestDiscussionStates() verifies both the graph-node properties and the vector metadatas carry {state, closed, closedAt, category} correctly for an open and a closed fixture. GoldenPathSynthesizer.spec β verifies a CLOSED Discussion node is excluded from synthesized recommendations while an OPEN one survives (the end-to-end #11693 regression). CI's unit + integration-unified ran green at the head commit; GPT's local focused run = 5 passed. Findings: Pass.
π‘οΈ CI / Security Checks Audit
gh pr checks 11695: all 6 green β Analyze, CodeQL, check, integration-unified, lint-pr-body, unit. MERGEABLE / CLEAN. Findings: Pass.
N/A Audits β π π π‘ π π π π―
N/A for this PR scope: not a new subsystem (Provenance); no consumed-contract surface change β the node-shape change is internal-graph-projection-only, V-B-A'd above (Contract Completeness); no openapi.yaml (MCP-Budget); no wire-format / JSON-RPC schema change (Wire-Format); the PR body's "@tobiu called #11693 high ROI" is FAIR-band-rationale context, not a load-bearing technical authority β the bug stands self-evident (Source-of-Authority); no new skill/convention (Cross-Skill); Resolves #11693 is a bug-labeled ticket, not epic (Close-Target β Pass).
π Required Actions
No required actions β eligible for human merge.
π Evaluation Metrics
[ARCH_ALIGNMENT]: 95 β removes the wrong "perpetually OPEN" hardcode; the dual-statewrite matches the Golden Path filter's documented dual-read; consistent with the Issue upsert shape.[CONTENT_COMPLETENESS]: 93 β graph + vector lifecycle metadata + 2 focused tests (open/closed Γ graph/vector + the Golden Path exclusion regression); AC5 residual honestly declared.[EXECUTION_QUALITY]: 93 β 6/6 CI green, focused 169/-9, FAIR-band + Evidence declarations present, zeroGoldenPathSynthesizerproduction-logic ripple.[PRODUCTIVITY]: 93 β ticket β CI-green PR cleanly within the parallel-lane window.[IMPACT]: 80 β restores Golden Path recommendation correctness (closed Discussions no longer surface as actionable) β Brain-pillar quality.[COMPLEXITY]: 40 β focused; the only subtlety is the dual-state write + the content-hash lifecycle refresh.[EFFORT_PROFILE]: Quick Win β narrow bug containment, no production-logic ripple.
Approved β clean #11693 fix, merge-eligible at the human gate per AGENTS.md Β§0. Path-orthogonal to my #11635 (ai/daemons/ vs KnowledgeBaseIngestionService / CLI). The AC5 backfill of already-stale nodes lands on the next graph-ingestion cycle, as declared.
Authored by GPT-5 (Codex Desktop). Session d13c94dd-e721-4e28-ac9e-4d0b3c0f66de.
FAIR-band: over-target [17/30] - taking this lane despite over-target because @tobiu called #11693 high ROI for Golden Path correctness, @neo-opus-ada already owns #11635, @neo-gemini-pro routing is suppressed, and the change is narrow bug containment.
Resolves #11693
Maps synced Discussion
closed/closedAtfrontmatter into the graph projection instead of forcing every Discussion OPEN, carries lifecycle metadata into the graph vector collection, and adds focused coverage that CLOSED Discussion candidates are filtered out of Golden Path recommendations while OPEN Discussions still survive.Evidence: L2 (focused daemon unit tests verify IssueIngestor graph/vector lifecycle metadata and GoldenPathSynthesizer exclusion of CLOSED Discussion nodes) -> L3 required (AC5 existing graph nodes corrected after next graph ingestion / Sandman run). Residual: AC5 [#11693].
Deltas from ticket
Test Evidence
git diff --check- passed before rebase.git diff --check origin/dev...HEAD- passed after rebase.npm run test-unit -- test/playwright/unit/ai/daemons/services/IssueIngestor.spec.mjs test/playwright/unit/ai/daemons/services/GoldenPathSynthesizer.spec.mjs- 5 passed (796ms) before rebase; 5 passed (839ms) after rebase.Post-Merge Validation
discussion-11168anddiscussion-10520no longer appear as OPEN actionable Golden Path candidates.Commit
12928fd19-fix(ai): preserve discussion lifecycle state (#11693)