-
Notifications
You must be signed in to change notification settings - Fork 28
Night Watch PM
Assigned to: Cindy's Navi (cixzhang)
Goal: Keep tasks, issues, and wiki tidy and navigable.
Review all open issues for completeness:
gh issue list --repo facebook/astryx --state open --limit 100 \
--json number,title,labels,body,comments,createdAt \
--jq '.[] | {number, title, labels: [.labels[].name], bodyLength: (.body | length), commentCount: (.comments | length)}'An implementable issue needs:
| Category | Required | If Missing |
|---|---|---|
enhancement (new component) |
API sketch (props), visual reference, usage example | Comment asking for the missing piece |
enhancement (feature) |
Which component, behavior changes, before/after | Comment asking for specifics |
bug |
Steps to reproduce, expected vs actual, browser/version | Comment asking for repro steps |
discussion |
A clear question or decision | No action — discussions are open-ended |
vibe-test |
Auto-generated | Skip |
Comment template:
This issue needs a bit more detail before it can be picked up for implementation:
- [ ] {specific missing item}
- [ ] {specific missing item}
Once these are filled in, this is ready to build. Happy to help draft any of these if useful.Do NOT comment on issues that:
- Already have a linked PR
- Were filed in the last 24 hours (give the author time)
- Are labeled
discussionordesign - Already have a triage comment from a previous run
If an issue is missing labels, add them:
- Component name mentioned →
component - Bug report →
bug - Feature request →
enhancement - Theming related →
theming - Unclear scope →
discussion
gh issue edit {number} --repo facebook/astryx --add-label "{label}"Maintain the wiki as a clean, navigable knowledge base. Clone the wiki repo and run these checks:
git clone https://github.com/facebook/astryx.wiki.git /tmp/xds-wiki
cd /tmp/xds-wiki| Rule | Check | Fix |
|---|---|---|
| No broken links | Every [[Page Name]] in every .md file must resolve to an existing file |
Fix the link or remove it. If the target page should exist, create a stub. |
| No orphan pages | Every page must be reachable from Home (directly or via a linked page) | Add link from the appropriate section, or move to Research Archive if historical. |
| Home stays current | Home links to all major active architecture/process pages | Add missing links. Remove links to pages that no longer exist. |
| Home descriptions accurate | Every link on Home has a description that matches the page's actual content | Read the linked page and update the Home description if it's stale or misleading. |
| Night Watch roles linked from Roles page | All Night-Watch-*.md files must be linked from Night Watch Roles, NOT from Home directly |
Add missing role links to Night-Watch-Roles.md. |
| Historical pages in archive | Pages marked as explorations, not-implemented, or historical belong in Research Archive, not Home | Move the Home link to Research-Archive.md. |
| Stale pages flagged | Pages not updated in 30+ days get reviewed | If still accurate, leave. If outdated, update or flag with a note. If irrelevant, move to Research Archive. |
| No pipe-syntax links |
[[display text|slug]] breaks — use [[Page Name]] only |
Convert to simple [[Page Name]] format. |
# Check all wiki links resolve
cd /tmp/xds-wiki
for f in *.md; do
grep -oP '\[\[([^\]]+)\]\]' "$f" | sed 's/\[\[//;s/\]\]//' | while read title; do
[[ "$title" == \#* ]] && continue # skip anchor links
file=$(echo "$title" | tr ' ' '-').md
if [ ! -f "$file" ]; then
echo "BROKEN: $f -> [[$title]]"
fi
done
done# Check for orphan pages (not linked from anywhere)
for f in *.md; do
[ "$f" = "Home.md" ] && continue
title=$(basename "$f" .md | tr '-' ' ')
if ! grep -rl "$title" --include='*.md' . | grep -qv "$f"; then
echo "ORPHAN: $title ($f)"
fi
doneThis check is mandatory every run. It catches pages that aren't orphans (they're linked from sub-pages) but are missing from Home's top-level navigation.
# Find pages not linked from Home that aren't Night Watch role sub-pages or Research Archive entries
cd /tmp/xds-wiki
HOME_LINKS=$(grep -oP '\[\[([^\]]+)\]\]' Home.md | sed 's/\[\[//;s/\]\]//' | tr ' ' '-')
ARCHIVE_LINKS=$(grep -oP '\[\[([^\]]+)\]\]' Research-Archive.md | sed 's/\[\[//;s/\]\]//' | tr ' ' '-')
ROLES_LINKS=$(grep -oP '\[\[([^\]]+)\]\]' Night-Watch-Roles.md | sed 's/\[\[//;s/\]\]//' | tr ' ' '-')
for f in *.md; do
[ "$f" = "Home.md" ] && continue
slug=$(basename "$f" .md)
# Skip if linked from Home
echo "$HOME_LINKS" | grep -qx "$slug" && continue
# Skip if linked from Research Archive
echo "$ARCHIVE_LINKS" | grep -qx "$slug" && continue
# Skip if it's a Night Watch role page linked from Roles
echo "$ROLES_LINKS" | grep -qx "$slug" && continue
# Skip Night-Watch-Roles itself (linked from Home via overview)
[[ "$slug" == "Night-Watch-Roles" ]] && continue
echo "NOT ON HOME: $slug"
doneFor each page reported as NOT ON HOME:
- Read the first few lines — is it an active process/architecture page, or historical/exploratory?
- Active pages (processes people follow, architecture docs, contribution guides) → add to the appropriate Home section
- Historical/exploratory pages → should already be in Research Archive. If not, add them there.
- Redirect pages (content moved elsewhere) → no action needed, they exist for link stability
For each link on Home.md:
- Open the linked page and read the first few sections
- Verify the Home description still matches the page content
- If the page has evolved significantly (new sections, changed scope), update the Home description
- If a link points to a page that's become irrelevant or historical, move it to Research Archive
- Check if any important new wiki pages exist that aren't linked from Home — add them to the right section
- Broken links: Fix or remove immediately.
- Stale Home descriptions: Update to reflect what the page actually covers today.
- Outdated content: If a page references old APIs, removed features, or superseded processes, update it. If the whole page is obsolete, move to Research Archive with a deprecation note at the top.
- Missing pages: If Home or another page references something important that should exist (e.g. a new architecture page), create a stub with a TODO.
- Stale formatting: Normalize wiki link syntax. No pipe links, no broken anchor references.
- Don't delete wiki pages (move to Research Archive instead)
- Don't rewrite content for style — only fix factual accuracy and broken links
- Don't add pages without checking they're linked from somewhere
- Don't modify the Research Archive structure without reason
After making changes, commit and push:
cd /tmp/xds-wiki
git add -A
git commit -m "wiki(night-watch): <summary of changes>"
git push origin masterRun a thorough pass over open issues to close completed work and consolidate duplicates.
Start with 4a — it's the highest-value, most automatable step and must run every night.
This is the most important task hygiene step. Run it every night, no exceptions.
Goal: Find PRs merged since the last PM run, match them to open issues, close what's resolved.
# Step 1: Get PRs merged in the last 48 hours (covers gaps if a run was missed)
MERGED_PRS=$(gh pr list --repo facebook/astryx --state merged --limit 50 \
--json number,title,body,mergedAt,labels,files \
--jq '[.[] | select(.mergedAt > (now - 172800 | strftime("%Y-%m-%dT%H:%M:%SZ")))]')
echo "$MERGED_PRS" | jq '.[].title'For each merged PR:
-
Check if it already closed an issue automatically (body contains "fixes #", "closes #", "resolves #" with a valid issue number). If yes, verify the issue is actually closed — if it's still open despite the keyword, close it now.
-
Extract the component name and scope from the PR title:
-
fix(Selector): forward HTML attrs→ component=Selector, type=fix -
feat: add Banner→ component=Banner, type=feat -
chore(deps): bump vitest→ skip (dependency bumps don't resolve feature issues)
-
-
Search open issues for matches:
gh issue list --repo facebook/astryx --state open \ --search "<component or keyword from PR title>" \ --json number,title,body,labels --limit 10 -
Read both the PR and candidate issues to confirm resolution. Match criteria:
Signal Confidence Action PR body explicitly says "addresses #X" or "related to #X" without closing keyword High Close the issue PR title is semantically equivalent to issue title (same component + same fix/feat) High Close the issue PR touches the exact files/behavior the issue describes High Close the issue PR adds a component that the issue requested High Close the issue PR title mentions the component but does different work Low Don't close Component name match alone without behavioral overlap Low Don't close -
Close matched issues:
gh issue close <number> --repo facebook/astryx --reason completed \ --comment "Resolved by #<PR number> (merged <date>)."
-
Partial matches — PR addresses some but not all of what the issue asks:
gh issue comment <number> --repo facebook/astryx \ --body "Partial progress: #<PR> shipped <what was done>. Remaining: <what's left>."
Do NOT close issues where:
- The match is ambiguous or based on component name alone
- The issue is labeled
discussionordesign - The issue was filed in the last 48 hours
- You're not confident the PR fully addresses the described problem
Track what you processed in state so you don't re-process the same PRs:
{
"pm": {
"lastProcessedMergedPRs": [2510, 2507, 2505],
"lastMergedPRScanAt": "2026-06-09T09:00:00Z"
}
}Search for open issues referenced in recently merged PR titles or bodies (e.g. "fixes #123", "closes #123", "resolves #123"). If the linked PR is merged and the issue is still open, close it:
gh issue close <number> --repo facebook/astryx --reason completed \
--comment "Closing — completed by #<PR number> (merged <date>)."For open issues requesting a component (e.g. "feat: Foo"), check if it already exists:
# List open component/enhancement issues
gh issue list --repo facebook/astryx --state open --label enhancement \
--json number,title --limit 100
# For each, check if the component directory exists
ls packages/core/src/<ComponentName>/ 2>/dev/null
ls packages/lab/src/<ComponentName>/ 2>/dev/nullIf the component exists in core or lab, find the PR that added it and close the issue:
gh pr list --repo facebook/astryx --state merged --search "<ComponentName>" \
--limit 5 --json number,title,closedAt
gh issue close <number> --repo facebook/astryx --reason completed \
--comment "Shipped in PR #<number>."Only the most recent nightly vibe test results issue should stay open. Close all older ones every run.
Why this must run every night: The Vibe Test Runner files a new results issue at ~4am, but the PM runs at 2am. This means there's always a previous-night's issue that needs closing. Do not skip this step.
# Get all open vibe-test results issues (not feature requests)
gh issue list --repo facebook/astryx --state open --label vibe-test \
--json number,title,createdAt \
--jq '[.[] | select(.title | test("^Nightly Vibe Test|^Vibe Test Results"))] | sort_by(.createdAt) | reverse'Keep ONLY the newest results issue open. Close all others:
gh issue close <number> --repo facebook/astryx --reason completed \
--comment "Superseded by newer vibe test results in #<newest_number>."Do NOT close vibe-test issues that are feature requests or explorations (e.g. "Night Watch: Add 'Design' dimension", "Exploration: CLI vs MCP").
If two or more open issues cover the same feature surface:
- Keep the most detailed/recent one
- Close the others with
--reason "not planned"and a comment pointing to the surviving issue:Consolidated into #<surviving_number>. - Update the surviving issue's title if needed to cover the broader scope
Each night, audit 5–10 open issues to determine if they've been resolved, superseded, or are still relevant. Work through issues oldest-first, tracking progress in state so you don't re-audit the same issues.
# Get open issues (exclude vibe-test)
gh issue list --repo facebook/astryx --state open --limit 100 \
--json number,title,labels,body,createdAt \
--jq '[.[] | select(.labels | map(.name) | index("vibe-test") | not)] | sort_by(.createdAt)'Pick the next 5–10 issues from the queue that haven't been audited recently (check auditedIssues in state).
For each issue, determine its status:
| Check | How | Action |
|---|---|---|
| Resolved by merged PR | Search merged PRs for the component/feature: gh pr list --state merged --search "<component or keyword>" --limit 10 --json number,title,mergedAt,body. Read the PR to confirm it addresses the issue. |
Close with comment linking the PR |
| Component/feature now exists | Check packages/core/src/ and packages/lab/src/ for the requested component or feature |
Close with comment noting where it shipped |
| Superseded by newer issue | Check if a newer issue covers the same ground with more detail or broader scope | Close older one, link to the newer issue |
| No longer relevant | The issue references removed APIs, old architecture, or features that were intentionally not built | Close as not planned with brief explanation |
| Still open and valid | None of the above apply — the issue describes work that hasn't been done | Leave open, no action |
Matching heuristics for finding resolving PRs:
| Signal | Confidence |
|---|---|
| PR title contains issue's component name + same verb (fix/feat/add) | High |
| PR touches files in the same component directory the issue describes | High |
| PR title is semantically equivalent to issue title | Medium |
| PR body or commits reference the same behavior described in the issue | Medium |
| Component name match alone without behavioral overlap | Low — don't close |
For each resolved issue:
gh issue close <number> --repo facebook/astryx --reason completed \
--comment "Resolved by #<PR number> (merged <date>)."For superseded issues:
gh issue close <number> --repo facebook/astryx --reason "not planned" \
--comment "Superseded by #<newer_issue_number> which covers this with broader scope."For partially addressed issues: Don't close — comment noting what was shipped and what remains:
gh issue comment <number> --repo facebook/astryx \
--body "Partial progress: #<PR> shipped <what was done>. Remaining: <what's left>."Do NOT close issues where:
- The match is ambiguous or based on component name alone
- The issue is labeled
discussionordesign - The issue was filed in the last 48 hours
- You're not confident the PR fully addresses the described problem
State tracking:
Track audited issues in memory/xds-night-watch-state.json under the pm key:
{
"pm": {
"auditedIssues": {
"123": { "auditedAt": "2026-04-19", "result": "closed", "resolvedBy": "#456" },
"124": { "auditedAt": "2026-04-19", "result": "open", "note": "still valid" }
},
"auditCursor": 0
}
}Advance auditCursor by the number of issues audited each night. When you reach the end of the list, reset to 0 (full cycle complete — issues may have changed since first pass).
- Flag issues open 30+ days with no activity
- Ensure issue-to-PR linkage is visible (PRs should reference the issue they close)
Track state in memory/xds-night-watch-state.json:
{
"role": "pm",
"lastRun": "2026-02-26T06:00:00Z",
"triagedIssues": {},
"labeledIssues": [],
"wikiCheckedAt": null,
"runsToday": 0
}