Originally created by: Akarsh-Hegde
/search/issues endpoint with the GitHub Projects v2 GraphQL APImeridian setup — project node IDs stored as GITHUB_PROJECT_IDSGITHUB_TOKEN is now the only required env var; GITHUB_ORG and GITHUB_REPOS removedstatus_category so tasks show the right state in the dashboardgh CLI_try_gh_token pulls the token straight from the gh CLI and grants any missing scopes through gh's browser flow — no personal access token needed. It falls back to a manual PAT prompt only when gh is unavailable. _pick_github_projects then lists personal + org projects to choose from.
A prior revision referenced
_try_gh_tokenbut never defined it, so setup fell through to the PAT prompt. It's now defined in bothinstall.sh(source installs) andscripts/install-from-bundle.sh(bundle installs).
repo, read:org, read:projectCorrected from the over-provisioned project (write) to read:project. meridian only reads Projects v2 via GraphQL and posts worklog / task-update issue comments under repo — it never mutates a project board. Verified three ways: GitHub's own INSUFFICIENT_SCOPES response, the GraphQL docs, and a codebase grep (the only mutation is Linear's commentCreate).
Daemon synced with a browser-issued gho_ OAuth token (no PAT): github tasks refreshed upserted_count=3 — the 3 viewer-assigned issues, with the Project Status column correctly mapping #194 → in_progress.
Merging this is necessary but not sufficient for meridian setup to use the new flow:
curl … bootstrap.sh | bash): meridian setup is owned by npm's meridian.js, which re-extracts the published release bundle — it will keep showing the old GITHUB_ORG prompt until a new release is cut.To test the branch now: install from source — git clone && ./install.sh (or check out this branch and re-run ./install.sh).
:::bash
meridian setup # gh token auto-extracted, project picker shown
GITHUB_TOKEN=gho_… (or ghp_…)
GITHUB_PROJECT_IDS=PVT_kwDOEMqA_c4BZ-xP
The daemon reads the
.envin itsWorkingDirectory:~/.meridian/app/.envfor bundle installs, the repo.envfor source installs. Write the config to the right one.
gh browser flow grants read:project and writes GITHUB_TOKENgho_ token → upserted_count=3#194 → in_progress)meridian setup (source install) end-to-end🤖 Generated with Claude Code
Originally posted by: adityaharishch
Code Review: 8 Findings
🔴 Critical Issues
1. IssueContent deserialization fails on non-Issue items
{}for non-Issue project items (PRs, drafts). TheIssueContentstruct has all required fields without#[serde(default)], causing deserialization to fail.2. Partial project fetch success causes task deletion
prune()is called with only A's task keys, deleting B's previously-synced tasks.prune()when all projects succeed, or track which projects failed to exclude their tasks.🟡 Maintenance Concerns
3. Bash function duplication (install.sh:106 & 139)
_try_gh_token()and_pick_github_projects()duplicated verbatim inscripts/install-from-bundle.sh4. Title-stamping logic diverges (segment.rs:720 vs indexer.rs:532)
indexer.rstrims and filters empty;segment.rscaps without guards🟠 Efficiency Issues
5. Redundant JSON deserialization (install.sh:161)
6. Sequential project fetches (github.rs:1873)
project_idsserially; could usetokio::join_all()for parallelism7. Window recalculated every drain tick (summariser/mod.rs:1255)
8. In-memory attempt ledger resets on restart (summariser/mod.rs:1213)
Recommendation: Address the two critical GitHub issues (#1, [#2]) before merge. Duplication and efficiency findings are lower priority.
Related
Tickets:
#2Originally posted by: Akarsh-Hegde
Thanks for the review. Both critical findings are fixed in b5df2c0.
🔴 Critical — fixed
1. Non-Issue items broke deserialisation ✅
contentis nowOption<serde_json::Value>, parsed intoIssueContentper ISSUE item — a PR/draft{}(or redactednull) is skipped instead of failing the whole project's parse. Added amixed_content_project_deserialisesregression test (Issue + PR{}+ draftnull).2. Partial fetch deleted unrelated tasks ✅
Added an
all_okguard:prune()(and the empty-keys full-clear) now run only when every project fetched successfully. A partial failure upserts what it got and preserves the rest until the next clean sync.Verified: builds, clippy clean, 212 tests pass.
Lower-priority — disposition
main's coding-agent code and entered this branch via themainmerge; they aren't changes this PR introduces, so they're out of scope here (and [#8] is the acknowledged intentional trade-off). Happy to file a follow-up if you'd like them tracked.Related
Tickets:
#6Tickets:
#7Tickets:
#8Originally posted by: Akarsh-Hegde
Update — all remaining review items handled.
Done on this PR (440cdd8)
_try_gh_token+_pick_github_projectsintoscripts/lib-github-setup.sh, sourced by bothinstall.shandscripts/install-from-bundle.sh, and added topackage-release.sh's bundle cp-list so fresh installs ship it. Obsolete "keep in sync" comments removed._pick_github_projectsnow parses the GraphQL response in a singlepython3pass (id<TAB>labelper line) instead of twice.futures::join_all(already a direct dep), preserving theany_ok/all_oksemantics.Split to [#200] (it's
main's code, not this PR's)clean_titlehelper used by bothindexer::stamp_titleandsegment::parse_session_segments. → https://github.com/Meridiona/meridian/pull/200Evaluated, intentionally left as-is
daysis computed once perdrain()call (every sweep), not per row, and isUtc::now()-based on purpose: hoisting it out of the loop freezes it at the daemon's startup date and breaks the midnight rollover the window exists to handle. The suggestion would be a regression. Cost today: twoformat()calls per ~10-min tick.MAX_ROW_ATTEMPTSare persisted viadb::write_dead_letter(task_method='subprocess_error', excluded fromfetch_pendingacross restarts). Only partial 1–2 counts reset on restart, which is the documented "restart retries cleanly" intent — so the cap isn't bypassable for its purpose. Happy to DB-persist the attempt counter too if you'd prefer that across crashes — just say the word.Related
Tickets:
#200Ticket changed by: Akarsh-Hegde
Originally posted by: adityaharishch
🎉 This PR is included in version 1.32.0 🎉
The release is available on:
v1.32.0Your semantic-release bot 📦🚀