Frontmatter
| title | chore(data-sync-pipeline): reduce DevIndex Spider loop from 3x to 1x (#10113) |
| author | tobiu |
| state | Merged |
| createdAt | Apr 20, 2026, 1:15 AM |
| updatedAt | Apr 20, 2026, 1:18 AM |
| closedAt | Apr 20, 2026, 1:18 AM |
| mergedAt | Apr 20, 2026, 1:18 AM |
| branches | dev ← fix/10113-devindex-spider-single-run |
| url | https://github.com/neomjs/neo/pull/10115 |

Input from Claude Opus 4.7 (Claude Code):
❋ # PR Review Summary
Status: Approved — ready for human QA
Self-Review Opening: Self-review of #10113. One-line CI workflow change (3-iteration bash loop → single invocation). Trivial execution; the rationale is architectural and was anchored against
learn/guides/devindex/primitives (Backpressure Valve atSpider.mjs:97, Cleanup Service, 30-day Penalty Box TTL). No code paths, no JSDoc surface, no tests necessary. Short review deliberately.
📊 Evaluation Metrics
[ARCH_ALIGNMENT]: 95 — No framework code touched; yaml tuning anchored to documented architectural primitives rather than reinventing them.[CONTENT_COMPLETENESS]: 90 — Fat Ticket filed (#10113) with full rationale; PR body cites specific file:line references (Spider.mjs:97, config value, guides). No JSDoc surface since yaml.[EXECUTION_QUALITY]: 90 — One-line change, no tests required for a config knob. Rebased onto fresh origin/dev (including merged #10114) before push for clean history. Minor: no yaml-syntax dry-run step; visual inspection sufficient at this size.[PRODUCTIVITY]: 95 — Both AC items met pre-merge.[IMPACT]: 40 — Narrow CI tuning. Observable effect on rate-limit budget + Pending influx, but not framework-critical.[COMPLEXITY]: 8 — Smaller-than-trivial.[EFFORT_PROFILE]: Quick Win — minimum-code change, direct impact on companion #10114's diagnostic hypothesis validation.
🕸️ Context & Graph Linking
- Target Epic / Issue ID: Resolves #10113
- Related Graph Nodes:
- Companion: #10114 / #10112 (diagnostic restoration; this PR removes pressure, that PR restores visibility)
- Noted-not-filed:
tracker.json(~49,649) vsusers.jsonl(~50,000) count gap — 351 users without tracker entries. Captured in PR body; confirm before filing as its own ticket.
🧠 Graph Ingestion Notes
[RETROSPECTIVE]: Thefeedback_audit_subsystem_guides_before_architectural_claimsmemory (saved earlier in session) prevented the premature Ticket C proposal during this work — the devindex guide tree made the existing architectural primitives visible, and the PR body cites them specifically. Memory paid dividends within the same session. Reinforces the value of Consolidate-Then-Save feedback capture.
[TOOLING_GAP]: Same Self-Review Detection heuristic issue flagged on PR #10114 recurred here —query_raw_memoriesfor#10113returned prior-ticket memories via semantic similarity but no direct#10113match (session hadn't persisted a memory containing the literal ticket number yet when the review fired). Manually overrode based on factual authorship. Not re-flagging as a distinct finding; just noting that the prior observation on PR #10114 applies.
[KB_GAP]: None.
📋 Required Actions
Zero Blockers. Zero Nits.
- Post-merge validation (unavoidable): observe next
data-sync-pipelineCI run — end-of-run GraphQL rate-limit remaining, total workflow duration, whetherlabels.mjsstep completes cleanly. Combined with #10114's diagnostic restoration, this confirms or refutes the rate-limit-429 hypothesis empirically.
Handing off to human QA per §5 of
pull-request-workflow.md. DO NOT auto-merge.
Summary
Changes the DevIndex Spider step in
.github/workflows/data-sync-pipeline.ymlfrom a 3-iteration bash loop to a single invocation. Reduces GraphQL rate-limit budget consumption in the hourly CI pipeline, which was contributing to downstream failures in the same workflow (see companion PR #10114 / ticket #10112 for the diagnostic-layer work).The Change
- - name: Run DevIndex Spider (3x Loop) + - name: Run DevIndex Spider env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - for i in 1 2 3; do - echo "Starting Spider Run $i/3..." - npm run devindex:spider -- --strategy random - done + run: npm run devindex:spider -- --strategy randomOne step, no other workflow changes.
Why Now
The 3x loop made sense during bootstrapping when discovery throughput (finding top-50k candidates) was the bottleneck. The DevIndex is now at the saturation state the architecture was designed around:
users.jsonlat the 50kmaxUserscapthreshold.jsonraised accordingly —Updater's Meritocracy filter aggressively prunes below-threshold candidatestracker.jsonsits near cap (~49,649), kept in sync viaCleanup's pruning (perlearn/guides/devindex/data-factory/DataHygiene.md)At saturation, extra spider iterations produce marginal new qualified users relative to their API cost. Concretely:
Spider.mjs:97Backpressure Valve (config.spider.maxPendingUsers: 2000) aborts runs 2 and 3, but each still costs state-loading cyclesUpdaterthroughput (~800/hour) is the actual bottleneck. Discovery oversupply queues candidates that mostly get threshold-rejected when Updater reaches them.Downstream Relationship
Companion PR #10114 (ticket #10112) restored diagnostic visibility on
LabelServicefailures in the same pipeline. The prevailing hypothesis — spider loop's 3× burn pushes subsequent GraphQL calls (labels, release, tickets index generation) into 429 territory — becomes empirically testable once #10114 lands and this PR removes the pressure. Two independent channels, drained in parallel.What Stays Untouched
Spider.mjscode — Backpressure Valve logic unchanged, no config tuningDevIndex.services.Cleanup— Garbage Collector + 30-day Penalty Box TTL unchangedon.scheduleThis is purely CI-step tuning.
Test Plan
data-sync-pipelinerun — total workflow duration, GraphQL rate-limit remaining at end-of-run, whetherlabels.mjsstep completes cleanlyRelated
tracker.json(~49,649) vsusers.jsonl(~50,000) count gap — 351 users exist without tracker entries, which would prevent re-update. Noted as a separate observation to confirm before filing; deliberately NOT scoped hereAvoided Traps
Spider.mjsor the Backpressure Valve config — architectural primitives are correct, this is purely a CI frequency knobUpdaterthroughput — separate large change with its own rate-limit exposureResolves #10113
🤖 Generated with Claude Code