Skip to content

design+impl: org-level GitHub Project as the conceptual-project layer — orchestrator-synced, dashboard-read #910

Closed

Description

@dezren39

design+impl: org-level GitHub Project as the conceptual-project layer — orchestrator-synced, dashboard-read

Drew's questions + direction (2026-10-25), building on the 2026-10-23/24 evaluation (recommended GitHub Projects: org-level, Board + Roadmap views over one item pool, label-gated auto-add, fleet-maintainable via gh/GraphQL, $0 incremental; write-up ~/workspace/your_files/github-projects-vs-linear-2026-10-23.md).

Why

Issues are the unit of work, but larger conceptual efforts (a program, a wave, a multi-repo set) have no first-class URL of their own today — they live in goal workspaces and epic-ish issues. An org-level Project gives each effort a stable place + URL, and the dashboard a canonical source for status that is not re-derived from scratch every hour.

Design

  • One org Project now (developing-today), designed to split later without migration: an Area field carries the conceptual project (e.g. id-train, pm-dashboard, lab-cluster). Splitting = filtered views per Area now; separate Projects per Area later is a view change, not a data move. The dashboard reads the same pool and can show all Areas together or filter to one.
  • Fields: Status (Todo / In Progress / In Review / Done), Area, Horizon (Today / Week / Month / Quarter — mirrors the dashboard horizons), Type (Task / Epic).
  • Items are issues. Pre-issue ideas may sit as draft items briefly but should become issues.
  • Epics = meta-issues: an issue with a task list of member issues + the epic label, itself a Project item with Type=Epic. Milestones connect clusters inside one repo (a wave, a release); the Project connects across repos. Both mechanisms coexist: milestone = time-boxed cluster in a repo, epic = cross-cutting grouping, Project = the whole portfolio.
  • Sync is single-writer. Agents NEVER write the Project directly — they keep working in GitHub issues only (comments, branches, PRs that reference the issue, assignment). The orchestrator reconciles the Project on its hourly pass from observable signals: issue added (label-gated auto-add: now / next / epic, or manual add) -> Todo; a branch or open PR referencing the issue, or an active session lined up on it -> In Progress; PR in review -> In Review; issue closed -> Done; blocked-by carried from issue text + the orchestrator's classification (same blockedBy data the dashboard already publishes). One writer = no sync races, no agent-side knowledge required.
  • Dashboard reads, never writes: the fleet-feed collector gains a projects section (GraphQL Projects v2 read), the aggregator renders Project views from it alongside the derived data; where the Project and derived state disagree, the disagreement is shown, not hidden (it is the reconciliation bug signal).
  • Known caveat to verify at build time: org Projects and personal-repo items (dezren39/nix) — the 2026-10-24 research said an org Project can't hold personal-repo items; verify current behavior, and if still true, nix items stay dashboard-only (the feed already covers them) and that limitation is documented on the Project.

Staged implementation

  1. Drew's go (org-level creation is his call).
  2. Create the Project + fields + Board and Roadmap views; README on the Project explaining the conventions in one screen.
  3. Label-gated auto-add workflow + the epic/milestone conventions written into the four repos' contributor docs where the fleet reads them.
  4. Orchestrator: add the reconciliation step to the hourly pass (bounded: at most ~25 item updates per run, mirroring its classification cap).
  5. Collector + aggregator: projects section in the feed; dashboard project page (this is a slice-3-manifest page — coordinate with impl(dashboard): slice 3 — pluggable pages (DNS register first), comments everywhere, agent/session identity registry #906).
  6. Backfill: current epics/programs (ID train, PM dashboard slices, lab cluster set) become items with Areas set.

Acceptance

  • Project exists with the fields/views above; a new labeled issue appears as a Todo item without human touching the Project.
  • Opening a PR that references a tracked issue moves its item to In Progress on the next orchestrator pass; merging/closing moves it to Done.
  • Dashboard shows the Project pool with an Area filter; an item's dashboard card links the Project item URL.
  • A blocked item shows its blocker on both the Project and the dashboard, from one recorded source.

Acceptance criteria

  • An org-level GitHub Project for developing-today exists with Status / Area / Horizon / Type fields and Board + Roadmap views over one item pool.
  • Label-gated auto-add (now / next / epic) is configured; epics are meta-issues carrying the epic label and Type=Epic.
  • The orchestrator's hourly pass is the single writer: it syncs item Status from issue/PR/session signals (Todo → In Progress → In Review → Done) and carries blocked-by from its existing classification.
  • No agent writes the Project directly; the dashboard's fleet-feed collector reads the Project via GraphQL (Projects v2) and renders a projects section without writing back.
  • A spot-check of several known issues shows Project Status matching their GitHub state after one orchestrator pass.

Activity

  1. developing-today commented on Oct 25, 2026

    @developing-today
    Contributor
  2. dezren39 commented on Oct 25, 2026

    @dezren39
    MemberAuthor

    Build report 2026-10-25 — stages 2, 3, 6(backfill): SPEC READY, creation BLOCKED on one auth step only Drew can do

    Blocker (verified four ways): creating an org Project needs a token with the OAuth project scope. None of the fleet's existing GitHub credentials has it:

    • gh CLI token (account dezren39): scopes admin:org, gist, repo, user, workflow — gh project list answers "missing required scopes [read:project]".
    • Backup gh token in Bitwarden (github-cli.hosts-yml): scopes admin:org, gist, repo, workflow — same gap.
    • GitHub MCP connector: exposes no project tools at all.
    • The fleet GitHub App ("developing-today kaneo", per ~/pm-stack/github-app-manifest.json on the laptop): repository permissions only (contents:read, issues:write, metadata:read, pull_requests:read) — no organization Projects permission, and adding one would itself need an org-owner UI approval.

    Unblock (one-time, ~1 minute, either option):

    1. Run gh auth refresh -s project --hostname github.com and approve the consent prompt — the fleet's existing gh then does everything below with no further steps; or
    2. Create a fine-grained PAT (resource owner: developing-today, organization permission Projects: Read and write) and file it in Bitwarden as github.project-token.

    Everything else is prepared so creation is mechanical the moment either lands.

    Prepared spec (stage 2)

    • Project: owner developing-today, title Developing Today, short description: "Org-level portfolio: every program, epic, and active task across the fleet's repos." Created via gh project create; remains private to the org.
    • Fields (all creatable via gh project field-create / GraphQL):
      • Status (built-in single-select, extended via updateProjectV2SingleSelectField): Todo / In Progress / In Review / Done.
      • Area (single-select): id-train, pm-dashboard, lab-cluster, fleet-ops. Small on purpose: Area is the split dimension — a future split is a saved view per Area, not a migration. New Areas get added only when a program outgrows these four.
      • Horizon (single-select): Today / Week / Month / Quarter.
      • Type (single-select): Task / Epic.
    • Views: there is no public API or gh support for creating project views, so the Board (grouped by Status) and Roadmap views are a one-time ~2-minute UI step at creation (or the default table view stands until then). Recorded here so nobody burns time re-discovering it.
    • README (set at creation; conventions on one screen):

      Developing Today — org portfolio

      Issues are the items; this project is the map, not the work. Agents never write this project — work happens in issues, branches, and PRs only. The orchestrator is the single writer: on its hourly pass it adds label-gated issues (now / next / epic) as Todo, moves items from observable signals (open PR referencing the issue or an active session → In Progress; PR in review → In Review; issue closed → Done), and carries blocked-by from issue text + its classification. Area = the conceptual project (id-train / pm-dashboard / lab-cluster / fleet-ops); filter a view by Area to see one program. Type=Epic marks meta-issues that group member issues; milestones group time-boxed clusters inside a single repo. The dashboard reads this project; it never writes it.

    Nix caveat — VERIFIED (docs), supersedes the 2026-10-24 research

    GitHub's current docs ("Adding items to your project") state a project can include issues and pull requests from any organization, and items are added by URL/search from any repository the adder can access — org projects are not restricted to org-owned repos. So the org Project can hold dezren39/nix items; the lab-cluster backfill below includes them. (One residual check at creation time: the first addProjectV2ItemById of a nix issue is the empirical proof — it is step 1 of the backfill run. Built-in auto-add remains per-repository and is not used; see stage 3.)

    Stage 3 — label gate DONE; auto-add realized as the orchestrator-side rule

    • The gate labels now exist in all four repos (created 2026-10-25, verified): now (d93f0b, "Org Project gate: active priority"), next (fbca04, "queued next"), epic (5319e7, "Meta-issue grouping multiple items") in developing-today/code, developing-today/opencode, developing-today/openchamber, dezren39/nix. No open issue carries them yet — the gate starts empty and correct.
    • GitHub's built-in auto-add workflow is configurable only in the project UI (Project → ⋯ → Workflows → Auto-add to project; one workflow per repository, label: filters supported) and cannot be created via API/gh. Per the fallback in this issue's plan, auto-add is therefore an orchestrator-side rule, specified here for stage 4 to implement verbatim: on each pass, for each of the four repos, add every open issue labeled now, next, or epic that is not already a project item, with Status=Todo and Type=Epic iff labeled epic; never remove items automatically. (Optional later: Drew enables the built-in UI workflows as a belt-and-suspenders duplicate — harmless because adds are idempotent.)
    • The epic/milestone conventions live in the Project README (above) as their interim home; folding them into the four repos' contributor docs is a repo-docs change, deliberately not bundled here.

    Backfill manifest (stage 6) — 27 items, all verified open/closed 2026-10-25, ready to add

    Item Area Type Status at add
    code#534 id: Phase 12 designs (task-list meta-issue) id-train Epic Todo
    code#539 id(ci): F11.8 benchmark harness id-train Task Todo
    code#542 id(world): F11.9 bytes-per-frame baseline id-train Task Todo
    code#544 id(world): F11.16 replay self-check id-train Task Todo
    code#851 design(aggregator): quota + throughput view pm-dashboard Task Todo
    code#852 design(aggregator): needs-you attention view pm-dashboard Task Todo
    code#898 impl(aggregator): slice 2 pm-dashboard Task Done
    code#899 impl(orchestrator): orchestration job pm-dashboard Task Done
    code#906 impl(dashboard): slice 3 pm-dashboard Task In Progress
    code#910 this issue pm-dashboard Task In Progress
    nix#508 EPIC: Basement Talos/Cozystack cluster program lab-cluster Epic Todo
    nix#501 hardware inventory + stats lab-cluster Task Todo
    nix#502 BMC/BIOS audit + KVM verification lab-cluster Task Todo
    nix#503 TALM bootstrap disk config lab-cluster Task Todo
    nix#504 storage pools (RustFS / LINSTOR-DRBD) lab-cluster Task Todo
    nix#505 egress strategy lab-cluster Task Todo
    nix#506 research: boats.dev lab-cluster Task Todo
    nix#507 OCI always-free maximization lab-cluster Task Todo
    code#819 remainder (PR #909 open, pending CI) fleet-ops Task In Review
    code#812 owner design decision fleet-ops Task Todo
    code#811 Jules item fleet-ops Task Todo
    code#818 remainder (blocked by #807) fleet-ops Task Todo
    code#861 rotate agent-auth Meta secret at source fleet-ops Task Todo
    code#902 impl(dns-registry) fleet-ops Task Todo
    code#903 fix(pm-stack): collector units vs recycle fleet-ops Task Todo
    code#908 id(web): /blob text/html XSS fleet-ops Task Todo
    opencode#431 standalone serve meta hang fleet-ops Task Todo

    Counts per Area: id-train 4, pm-dashboard 6, lab-cluster 8, fleet-ops 9. Horizon is left unset at backfill except #906 (Week); the orchestrator's measurement fills horizons in.

    Named next actions (unchanged ownership, not done here)

    Project URL: none yet — this comment is the record until the auth unblock lands; the creation run appends the URL here and to the daily log.

  3. added
    kind/featureNew feature or capability request
    source/humanFiled directly by a human
    priority/normalOrdinary priority (the default)
    effort/lLarge: multi-day or open-ended; expect staged check-ins
    area/infraInfrastructure, deployment, and operations
    meta/enrichedIntake review done: acceptance criteria, links, and normalized labels added
    on Oct 26, 2026
  4. dezren39 commented on Oct 26, 2026

    @dezren39
    MemberAuthor

    Intake review

    Fleet monitor intake pass (2026-10-25 run). Acceptance criteria appended to the body this pass (original body preserved verbatim above it).

    Related: #911 (the fleet work-picking jobs consulting the orchestrator's published state — enriched last monitor run; the Project described here is the conceptual layer above that same orchestrator), #902 (another standing-registry/dashboard build from the same 2026-10-25 direction batch).

    Notes: This is a design+implementation item, not a bug: nothing to reproduce. The single-writer rule (orchestrator syncs; agents and the dashboard never write the Project) is the load-bearing design decision — it keeps the protocol identical to how agents already work issues today. Label-gated auto-add (now / next / epic) means adoption is incremental: existing issues join the pool by label, no bulk migration needed.

    Risks: GitHub Projects v2 GraphQL field/option IDs are brittle across project edits — the sync should resolve fields by name each pass. Horizon/Status drift between the Project and the dashboard's own horizons is the main consistency risk; the design already mirrors the dashboard horizons deliberately.

    Suggested approach: Stand up the Project + fields first (manually, once), then the collector read (dashboard projects section), then the orchestrator sync last — each step is independently verifiable, and the read path proves the field model before the writer depends on it. Effort classed l (multi-part build).

  5. dezren39 commented on Oct 26, 2026

    @dezren39
    MemberAuthor

    Creation run 2026-10-25 — BUILT ✅

    Project: Developing Today — https://github.com/orgs/developing-today/projects/4 (org developing-today, #4, private, id PVT_kwDOAZNvF84Bouay)

    Built with the Bitwarden-filed fine-grained token (github.project-token, Projects Read+write only, expires 2027-10-26). Verified end-to-end via API re-list after the build.

    Existing project #1 — inspected, left untouched (different design, not a partial build)

    Project #1 "code" (public) uses a lifecycle Status scheme (CREATED / DESIGNED / READY / BLOCKED / ACTIVE / STALLED / DONE / CANCELLED), has no Area/Horizon/Type fields, an empty README, and a single draft item ("dns alias in tf provider"). That is an older, different tracker — not an earlier cut of this spec — so the designed project was created fresh as #4 rather than bending #1 into a different shape. #1 is unchanged.

    What was built (per the spec in comment 6404216307)

    Remainders (named, unchanged ownership)

    • Board + Roadmap views: not created. There is no API/gh support for project views; the laptop Helium CDP endpoint is live, but driving the Projects UI automation to build and configure both views is not a quick operation, so per the run's stop rule they remain a one-time ~2-minute manual UI step (Board grouped by Status; Roadmap by Horizon/dates). The default table view shows all 27 items with every field until then.
    • Stage 4 — orchestrator reconciliation + auto-add rule: unchanged, owner keep-the-four-repos-healthy (orchestration-pass cron), as specified in the prep comment.
    • Stage 5 — collector feed projects section + dashboard rendering: unchanged, owner dashboard lane.

    Stages 2, 3, and 6 of this issue are now complete; the issue stays open only as the tracker for stages 4–5 and the views remainder.

  6. added a commit that references this issue on Oct 26, 2026
  7. dezren39 commented on Oct 26, 2026

    @dezren39
    MemberAuthor

    Stage 4 — FIRST reconciliation pass run 2026-10-26 ✅

    The reconciliation machinery is built and its first pass is complete. The Project is current against GitHub ground truth as of this run.

    Helper: project-reconcile.sh (bash) at workspace/goals/keep-the-four-repos-healthy/hidden_files/project-reconcile.sh in hatch-personal (committed). --dry-run prints proposals; --apply performs at most 25 Status updates per run, closed→Done first. Design choices per this issue's spec: Status field + option IDs are resolved by name on every run (IDs are brittle across project edits); Project reads/writes use the Bitwarden github.project-token (Projects-only) passed as GH_TOKEN per-command; all issue/PR/branch signals use the normal fleet gh auth. Signals per item: issue state + open PRs referencing it (issue-timeline cross-references ∪ PR closing-issue references ∪ title/body #N mentions ∪ PR head-branch naming) + branch-name matches, mapped closed → Done, open non-draft PR → In Review, draft PR or branch → In Progress, else Todo.

    First pass results — 27 items reviewed, 6 transitioned, 21 unchanged, 0 failed:

    Acceptance spot-check (fresh reads both sides, all match):

    Auto-add discovery (report-only this run; the hourly step applies it): gate labels now / next / epic verified present in all four repos. Labeled open issues not yet Project items: code 0, opencode 0, openchamber 0, dezren39/nix 1 — nix#672 (carries epic; would join as Status=Todo, Kind=Epic).

    Remainders (unchanged ownership): the hourly orchestration-pass body step that calls this helper is being added separately (dashboard-fix lane — this run deliberately touched no cron body); Board + Roadmap views are being created separately; Stage 5 (collector feed projects section + dashboard rendering) unchanged. A full pass takes ~2.5 min of gh calls, comfortable at hourly cadence. This issue stays open as the tracker for stages 4-hourly/5 and the views.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area/infraInfrastructure, deployment, and operationseffort/lLarge: multi-day or open-ended; expect staged check-inskind/featureNew feature or capability requestmeta/enrichedIntake review done: acceptance criteria, links, and normalized labels addedpriority/normalOrdinary priority (the default)source/humanFiled directly by a humanstatus:done

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions