Skip to content

pm: project automation foundation (pm/ folder + 2 GH Actions)#127

Merged
hanwencheng merged 6 commits into
mainfrom
pm/automation-foundation
May 24, 2026
Merged

pm: project automation foundation (pm/ folder + 2 GH Actions)#127
hanwencheng merged 6 commits into
mainfrom
pm/automation-foundation

Conversation

@hanwencheng
Copy link
Copy Markdown
Member

Summary

  • Introduces pm/ folder: declarative milestones + labels + issue assignments + 7 bash automation scripts + dashboard usage guide
  • Adds two GitHub Actions workflows so project-board automation runs on every event instead of as manual scripts:
    • pm-sync-fields-from-labels.yml — mirrors priority/p* + phase/v* labels into the project's Priority + Phase single-select fields on issues.labeled
    • pm-workflow-audit.yml — daily cron + push trigger; runs check-workflows.sh against pm/expected-workflows.json and opens a tracking issue on drift
  • Cherry-picked from claude/hopeful-mccarthy-15e5ba (which also has in-progress Rust + research changes not ready for main); 3 refs to docs/research/agent-iam-strategy.md were stripped because that doc lands in a separate PR

Why GH Actions instead of more scripts

Live verification of the API ceiling via GraphQL introspection: ProjectV2Workflow has only deleteProjectV2Workflow (no create/update mutation), and ProjectV2View has no create/update mutation at all. So workflow filter/trigger/action contents + custom view configuration are 100% UI-only. Every other PM automation surface (fields, items, field values, labels, milestones, issues) is fully API-driven, so we push it to GitHub Actions.

pm/PROJECT-DASHBOARD-GUIDE.md has the full three-tier matrix (built-in workflow / our GH Action / bash script) and a verdict table on what's automatable.

Bugs caught + fixed during live verification on litentry/projects/19

  • gh api -F type-coerces numeric option IDs to int → String! GraphQL mismatch. Fixed by using -f (raw-field) for option-ID parameters in sync-fields-from-labels.sh.
  • deleteProjectV2Field on a system-reserved name (Priority) renames the old field to Project <Name> instead of deleting it, leaving zombie clutter. Fixed by adding a cleanup_zombies pass at the top of setup-project-fields.sh.
  • setup-project-fields.sh first version skipped Priority because the built-in placeholder exists with zero options. Fixed by detecting + rebuilding empty single-select fields.

Required repo secret (for the GH Actions to authenticate)

The PM workflows need a token with org-project scopes — the default GITHUB_TOKEN does not have them. You set this once after merge:

# Fine-grained PAT with Org:Projects=read+write, Repo:Issues=read+write
gh secret set PM_PROJECT_TOKEN --repo litentry/agentKeys

Without this, both workflows will fail with Resource not accessible by integration.

Test plan

  • After merge, set the PM_PROJECT_TOKEN repo secret (see above)
  • Trigger sync workflow manually against one issue:
    gh workflow run pm-sync-fields-from-labels.yml --repo litentry/agentKeys -f issue_number=103
  • Verify the run completes green: gh run watch --repo litentry/agentKeys
  • Verify Priority + Phase fields are set on Demo: aiosandbox + Hermes + AgentKeys on ESP32 hardware #103 in the project UI
  • Trigger drift audit manually: gh workflow run pm-workflow-audit.yml --repo litentry/agentKeys
  • Verify daily cron schedule shows Next run: ~14:00 UTC in the workflow page
  • Add priority/p2 label to any open issue and confirm the sync workflow fires automatically (via issues.labeled trigger) and populates Priority=P2

What's NOT in this PR

  • docs/research/agent-iam-strategy.md (strategic positioning doc) — lands in a separate PR; the 3 broken refs to it were stripped from this PR's markdown
  • The 20 new issues spec data (pm/new-issues.json) is included but the issues were already created on GitHub from a prior branch state — the JSON is the record, not a trigger

New pm/ subfolder for GitHub project management automation. Treats
milestones / labels / issue categorization as code under version
control with idempotent shell scripts that reconcile GitHub state
to declarative JSON.

Files:
- pm/README.md — folder purpose + how to use
- pm/milestones.json — 7 roadmap milestones (M1-M7) source of truth
- pm/labels.json — 40-label taxonomy: area/ kind/ phase/ status/
  priority/ + extras (needs-arch-review, vendor-blocker)
- pm/issue-assignments.json — categorization of all 23 pre-existing
  open issues with milestone + labels + notes
- pm/new-issues.json — 20 new Phase 1-7 issues to create
- pm/arch-md-verification-report.md — #5/#6/#9/#37 verification
- pm/PROJECT-DASHBOARD-GUIDE.md — how to use projects/19 board +
  CI integration patterns
- pm/scripts/sync-milestones.sh — idempotent: creates/updates from
  milestones.json
- pm/scripts/sync-labels.sh — idempotent: creates/updates from
  labels.json
- pm/scripts/sync-issues.sh — idempotent: assigns milestone+labels
  to each issue in issue-assignments.json
- pm/scripts/create-issues.sh — idempotent: creates new issues from
  new-issues.json, skips if title already exists
- pm/scripts/audit.sh — read-only: groups open issues by milestone,
  flags uncategorized + missing area/* labels
- pm/scripts/add-to-project.sh — adds issues to litentry/projects/19
  (requires gh auth refresh -s project,read:project)

Executed in this session:
- Created 7 milestones (M1: First MCP demo + Volcano Ark PoC, M2:
  First vendor wedge, M3: Runtime neutrality, M4: Capability +
  revocation depth, M5: Native mobile + biometric, M6: TEE
  integration + security, M7: Standards + ecosystem)
- Created 40 labels across 5 namespaces (area, kind, phase,
  status, priority) + extras (needs-arch-review, vendor-blocker)
- Categorized 23 pre-existing open issues with milestones + labels
- Created 20 new issues (#107-#126) for Phase 1-7 work per the
  agent-iam-strategy.md roadmap
- Verified #5, #6, #9, #37 against arch.md — verdicts: #5 partially
  aligned (closed; lives as tier A in §15.3), #6 needs design
  refresh against current K11+SidecarRegistry, #9 already
  implemented as K3 HDKD per §6.2 (recommend close), #37 superseded
  by K11 WebAuthn per §K11 (recommend close)

Final state: 43 open issues, 100% categorized to milestones, 100%
labeled with area/*. No uncategorized issues.

Per user direction: did NOT merge / close #5/#6/#9/#37 even though
recommendations are clear. User to make final close decisions.
…s-fields strategy

Three fixes responding to user feedback:

1. add-to-project.sh: replace mapfile (bash 4+) with while-read loop
   for macOS bash 3.2 portability per CLAUDE.md project standard.
   Verified working: 'bash pm/scripts/add-to-project.sh 103' now
   successfully adds the issue to litentry/projects/19.

2. NEW pm/scripts/setup-project-fields.sh: creates the canonical
   project-level fields (Priority, Phase, Estimate, Iteration, Risk,
   Notes) via gh project field-create. Solves the 'cluttered Labels
   column' UX pain by letting the user split single-value PM
   concerns (priority, phase, status) out of the multi-value labels
   pile into typed field columns.

3. PROJECT-DASHBOARD-GUIDE.md: added 'Labels vs Fields — when to
   use which' section explaining the split:
   - Labels (repo-level, multi-value): area/*, kind/*, semantic
     flags like needs-arch-review, vendor-blocker
   - Fields (project-level, single-value): Priority, Phase, Status,
     Estimate, Risk
   Plus step-by-step instructions to migrate the cluttered Labels
   column to clean field-based grouping.

These don't change the strategic plan; they just fix the operational
PM-board ergonomics the user surfaced from running the script live.
User pointed out the project board has 10 built-in workflows that
replace much of what the scripts do. Updated guidance to prefer
workflows; scripts are fallback/batch tools.

PROJECT-DASHBOARD-GUIDE.md updates:
- Replaced the brief 'Recommended workflows' section with a full
  table of the 10 built-in workflows + their default state + what
  to configure
- New 'Script ↔ workflow split' table making clear which jobs use
  workflows vs scripts (workflows for runtime project events; scripts
  for repo-level state, batch creation, field definitions)
- One-time workflow configuration checklist (3 steps to get the
  Auto-add filter set, verify other green workflows, optionally
  enable Auto-archive)

add-to-project.sh updates:
- Header now flags this as PRIMARILY A BACKFILL / FALLBACK TOOL
- Lists three legit use cases: backfilling pre-existing issues,
  fallback when Auto-add workflow is misconfigured, adding from
  a different repo via PM_REPO override
- Pointer to PROJECT-DASHBOARD-GUIDE.md for workflow setup

No script behavior changes; only documentation tightens to match
the workflow-first reality.
… stay manual)

User asked if workflows can be programmatically checked. Partial yes:
GitHub's public GraphQL ProjectV2Workflow type exposes only:
  id, name, number, enabled, createdAt, updatedAt, project, fullDatabaseId
NOT the filter expression or action configuration (UI-only, not in
the public API).

So we get:
  ✅ 'is the workflow enabled' check
  ❌ 'does the workflow do the right thing' check (filter/action body)

New files:
- pm/expected-workflows.json: declarative source of truth for what
  workflows should be enabled + what each one's filter/action should
  do (free-text 'verify_in_ui' field that engineers cross-check
  against the UI)
- pm/scripts/check-workflows.sh: audits live workflows on
  litentry/projects/19 vs expected-workflows.json
  - Confirms enabled state matches
  - Flags unexpected workflows that exist but aren't in our list
  - Prints all per-workflow expected filter/action notes for
    manual UI verification
  - Exits 0 when all expectations match, 1 on mismatch (CI-friendly)

Live audit result (verified on litentry/projects/19): 7 expected
workflows enabled (Auto-add to project, Auto-add sub-issues to
project, Item added/closed, Auto-close issue, PR linked/merged),
4 optional workflows correctly disabled (Auto-archive, Code review
approved, Code changes requested, Item reopened). 11/11 match.

This script can be wired into a future CI workflow to alert on
drift if anyone disables Auto-add to project or similar.
Adds two GitHub Actions and one supporting script to push project automation
to its API ceiling. After this change, label-to-field sync and workflow drift
detection both run on every event / daily schedule instead of as manual scripts.

What landed:

- .github/workflows/pm-sync-fields-from-labels.yml: triggers on issues
  labeled/unlabeled/opened/transferred. Calls sync-fields-from-labels.sh
  to mirror priority/p* + phase/v* labels into the project's Priority + Phase
  single-select fields. workflow_dispatch variant for backfill.

- .github/workflows/pm-workflow-audit.yml: daily cron + push trigger.
  Runs check-workflows.sh against expected-workflows.json and opens (or
  comments on) a tracking issue when drift is detected.

- pm/scripts/sync-fields-from-labels.sh: backing script for the sync workflow.
  Forgiving mode (warns + skips when a field is missing rather than aborting),
  bash 3.2 portable, uses -f for option-ID strings to avoid gh api numeric
  coercion.

- pm/scripts/setup-project-fields.sh: now detects + rebuilds empty-placeholder
  single-select fields (GitHub's built-in Priority/Size ship with zero options)
  and cleans up "Project <Name>" zombie fields left behind when
  deleteProjectV2Field renames instead of deleting system-reserved names.
  Fully idempotent.

- pm/PROJECT-DASHBOARD-GUIDE.md: new "What's automated vs UI-only" verdict
  table (built-in workflow filter/action contents + custom views are 100%
  UI-only — no API mutation exists for either). New "Known gotcha" section
  on Priority-field zombies. Script-vs-workflow split rewritten as three-tier
  matrix (built-in / our GH Action / bash script).

Verification: tested live against litentry/projects/19. Backfilled 40+
issues onto board, synced Priority + Phase from labels on every one, zero
zombie fields remain. setup-project-fields.sh second-run shows all skips.

API ceiling discovered via GraphQL introspection: ProjectV2Workflow has
no create/update mutation (only delete). ProjectV2View has no create/update
mutation at all. Both are read-only via API, UI-only to configure.

Required repo secret for CI: PM_PROJECT_TOKEN (fine-grained PAT with
Projects=read+write, Issues=read+write). Documented in dashboard guide.
Three links in pm/README.md and pm/PROJECT-DASHBOARD-GUIDE.md pointed at
docs/research/agent-iam-strategy.md, which is still on a feature branch.
Replace with pointers to pm/milestones.json (the data that's actually on
this PR) so the rendered markdown doesn't 404 once merged.

The strategy doc + research folder land in a separate PR.
@hanwencheng hanwencheng merged commit 05c0b04 into main May 24, 2026
1 check passed
hanwencheng added a commit that referenced this pull request May 24, 2026
Merge origin/main into claude/hopeful-mccarthy-15e5ba to resolve conflicts
opened by PR #127's squash-merge landing on main. Plus cleanup of pm/
files that no longer fit the post-migration workflow.

## Conflict resolution

4 files had conflicting versions (main's pre-migration state vs our
post-migration state):
- pm/PROJECT-DASHBOARD-GUIDE.md → OURS (post-migration narrative)
- pm/README.md → OURS, then rewritten to drop refs to deleted files
- pm/labels.json → OURS (recolored area/*, red reserved for human attention)
- pm/scripts/setup-project-fields.sh → OURS (Urgent/High/Medium/Low + Kind)

## Re-deletions (main re-added; we re-removed)

Files we deleted in 47d503f got re-added by the merge because they
were on main from #127. Re-removed:
- .github/workflows/pm-sync-fields-from-labels.yml
- .github/workflows/pm-workflow-audit.yml
- pm/expected-workflows.json
- pm/scripts/check-workflows.sh
- pm/scripts/sync-fields-from-labels.sh

## Unused pm/ files removed (per user request)

- pm/scripts/sync-issues.sh: actively broken — references deleted
  labels (priority/p*, kind/*, phase/v*) that were removed in the
  migration. Running it today fails.
- pm/scripts/create-issues.sh: one-shot tool that created issues from
  new-issues.json. All 20 issues already created (#107-#126); running
  again would attempt to duplicate.
- pm/issue-assignments.json: historical record of pre-migration label
  assignments. Data references deleted labels.
- pm/new-issues.json: historical record of which 20 issues to create.
  All created. The refined-issue bodies are the source of truth now.
- pm/arch-md-verification-report.md: one-off arch.md compatibility
  verification for #5/#6/#9/#37. Job done.

## What remains in pm/

| Path | Status |
|---|---|
| pm/PROJECT-DASHBOARD-GUIDE.md | Active — dashboard usage |
| pm/README.md | Active — folder intro (rewritten) |
| pm/labels.json | Active — sync-labels.sh source |
| pm/milestones.json | Active — sync-milestones.sh source |
| pm/scripts/add-to-project.sh | Active — backfill tool |
| pm/scripts/audit.sh | Active — read-only state audit |
| pm/scripts/setup-project-fields.sh | Active — project field bootstrap |
| pm/scripts/sync-labels.sh | Active — applies labels.json |
| pm/scripts/sync-milestones.sh | Active — applies milestones.json |
| pm/scripts/sync-size-from-effort.sh | Active — one-shot Size population |
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant