feat(modules): no-provider plan check + read-only extension-points ls (§5.5 C4)
- apply: `check_extension_points_provided` (app nodes) — every EP visible on
the app's chain (its own + inherited) must have a provider: a same-apply
module, or one resolvable up-chain (override or default body). Else a clean
`pic plan` error instead of a runtime failure. Single-node only (the tree
path leans on the runtime backstop, like the dangling-import check).
- read-only surface: `extension_point_report` + `ExtensionPointInfo`;
`GET /{apps|groups}/{id}/extension-points` (AppRead / GroupScriptsRead);
`pic extension-points ls --app|--group` showing declared-vs-inherited + the
resolved provider (`app override` / `inherited default` / `unset`).
- `pic pull` round-trips an app's OWN declared EPs (filtered `declared_here`),
so pull→plan stays idempotent.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -153,6 +153,15 @@ enum Cmd {
|
||||
cmd: VarsCmd,
|
||||
},
|
||||
|
||||
/// Extension points (§5.5) — read-only view of the module names a node
|
||||
/// marks as overridable. Authored declaratively via the manifest
|
||||
/// `extension_points = [...]`; this lists them + (for an app) each one's
|
||||
/// resolved provider.
|
||||
ExtensionPoints {
|
||||
#[command(subcommand)]
|
||||
cmd: ExtensionPointsCmd,
|
||||
},
|
||||
|
||||
/// Files inspection — list a collection's blobs, download bytes, or
|
||||
/// delete a file. Read + delete only; writes go through scripts.
|
||||
Files {
|
||||
@@ -537,6 +546,18 @@ enum DomainsCmd {
|
||||
Rm { app: String, domain_id: String },
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
enum ExtensionPointsCmd {
|
||||
/// List a node's extension points. `--app` shows every EP visible on the
|
||||
/// app's chain with its resolved provider; `--group` shows the group's own.
|
||||
Ls {
|
||||
#[arg(long)]
|
||||
app: Option<String>,
|
||||
#[arg(long, conflicts_with = "app")]
|
||||
group: Option<String>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
enum ScriptsCmd {
|
||||
/// List scripts. With `--app`, scoped to one app; with `--group`, a
|
||||
@@ -1961,6 +1982,9 @@ async fn main() -> ExitCode {
|
||||
env,
|
||||
},
|
||||
} => cmds::vars::rm(group.as_deref(), app.as_deref(), &key, env.as_deref()).await,
|
||||
Cmd::ExtensionPoints {
|
||||
cmd: ExtensionPointsCmd::Ls { app, group },
|
||||
} => cmds::extension_points::ls(app.as_deref(), group.as_deref(), mode).await,
|
||||
Cmd::Files {
|
||||
cmd:
|
||||
FilesCmd::Ls {
|
||||
|
||||
Reference in New Issue
Block a user