feat(cli): pic projects ls + §7 M3/track-complete docs

§7 M3 (part 3) — the ownership track becomes inspectable, completing M1–M3.

- server: GET /api/v1/admin/projects (projects_api) lists every project + its
  owned-group count (projects repo list_with_counts, one GROUP BY); behind the
  /admin middleware, like the groups list.
- CLI: pic projects ls (cmds/projects.rs + client projects_list); the
  apply_ownership plan-preview journey now also asserts projects ls (plat owns
  exactly 1 group; teamb listed).
- docs: design §7 + CLAUDE.md record M3 shipped and the whole §7 multi-repo
  ownership track (M1 claim · M2 attach ceiling · M3 preview + projects ls)
  COMPLETE; deferred = structural-divergence + declarative tree shape + per-env
  approval gating.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-07-06 21:26:10 +02:00
parent 30fe160f16
commit f673922d89
11 changed files with 244 additions and 29 deletions

View File

@@ -58,6 +58,12 @@ enum Cmd {
cmd: GroupsCmd,
},
/// §7 multi-repo ownership projects (read-only).
Projects {
#[command(subcommand)]
cmd: ProjectsCmd,
},
/// Script management.
Scripts {
#[command(subcommand)]
@@ -490,6 +496,12 @@ enum AppsCmd {
},
}
#[derive(Subcommand)]
enum ProjectsCmd {
/// List all projects + how many group nodes each owns.
Ls,
}
#[derive(Subcommand)]
enum GroupsCmd {
/// List all groups (flat).
@@ -1509,6 +1521,9 @@ async fn main() -> ExitCode {
cmd: DomainsCmd::Rm { app, domain_id },
},
} => cmds::apps_domains::rm(&app, &domain_id).await,
Cmd::Projects {
cmd: ProjectsCmd::Ls,
} => cmds::projects::ls(mode).await,
Cmd::Groups { cmd: GroupsCmd::Ls } => cmds::groups::ls(mode).await,
Cmd::Groups {
cmd: GroupsCmd::Tree,