Skip to content

Night Watch PM

Cindy Zhang edited this page Jun 23, 2026 · 1 revision

Night Watch: PM Role

Assigned to: Cindy's Navi (cixzhang) Goal: Keep tasks, issues, and wiki tidy and navigable.


Hourly Checklist

1. Issue Triage — Ensure Implementability

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 discussion or design
  • Already have a triage comment from a previous run

2. Issue Labeling

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}"

3. Wiki Hygiene

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

Heuristics

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.

Link Validation Script

# 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
done

Home Completeness Check

This 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"
done

For each page reported as NOT ON HOME:

  1. Read the first few lines — is it an active process/architecture page, or historical/exploratory?
  2. Active pages (processes people follow, architecture docs, contribution guides) → add to the appropriate Home section
  3. Historical/exploratory pages → should already be in Research Archive. If not, add them there.
  4. Redirect pages (content moved elsewhere) → no action needed, they exist for link stability

Home Page Audit

For each link on Home.md:

  1. Open the linked page and read the first few sections
  2. Verify the Home description still matches the page content
  3. If the page has evolved significantly (new sections, changed scope), update the Home description
  4. If a link points to a page that's become irrelevant or historical, move it to Research Archive
  5. Check if any important new wiki pages exist that aren't linked from Home — add them to the right section

What to Clean Up

  • 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.

What NOT to Do

  • 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 master

4. Task Hygiene — Issue Gardening

Run 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.

4a. Recently Merged PRs → Close Resolved Issues (MANDATORY)

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:

  1. 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.

  2. 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)
  3. 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
  4. 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
  5. Close matched issues:

    gh issue close <number> --repo facebook/astryx --reason completed \
      --comment "Resolved by #<PR number> (merged <date>)."
  6. 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 discussion or design
  • 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"
  }
}

4b. Explicit PR References (Cleanup)

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>)."

4c. Component Feature Issues — Check if Shipped

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/null

If 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>."

4d. Superseded Vibe Test Results (MANDATORY)

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").

4e. Consolidate Duplicates

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

4f. Issue Audit — Batch Resolution Check (5–10 per night)

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 discussion or design
  • 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).

4g. Stale Issues

  • Flag issues open 30+ days with no activity
  • Ensure issue-to-PR linkage is visible (PRs should reference the issue they close)

State

Track state in memory/xds-night-watch-state.json:

{
  "role": "pm",
  "lastRun": "2026-02-26T06:00:00Z",
  "triagedIssues": {},
  "labeledIssues": [],
  "wikiCheckedAt": null,
  "runsToday": 0
}

Clone this wiki locally