test(cli): extension-point journeys + node-key manifest fix + docs (§5.5 C5)

- Move the manifest `extension_points` from a top-level key to an `[app]`/
  `[group]` node key (`ManifestApp`/`ManifestGroup` + a `Manifest::extension_points()`
  accessor). A bare top-level array placed after the node header was silently
  re-nested by TOML into that table and dropped; as a node key it parses
  unambiguously wherever it sits. build_bundle/pull/init updated.
- Journeys (live server + Postgres): a group default body resolves for an
  inheriting app; the app provides its own module and OVERRIDES the EP (the
  inverse of the Phase 4b sealed import); `extension-points ls` shows the
  provider; a body-less EP with no provider fails `pic plan`.
- Re-bless the schema snapshot (new `extension_points` table).
- Docs: §5.5 marked complete (extension points ) + CLAUDE.md current-focus.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-06-29 20:53:18 +02:00
parent 82b4579317
commit a049397bb0
9 changed files with 295 additions and 15 deletions

View File

@@ -113,6 +113,7 @@ fn scaffold_manifest(slug: &str, name: &str) -> Manifest {
slug: slug.to_string(),
name: name.to_string(),
description: None,
extension_points: Vec::new(),
}),
group: None,
scripts: vec![ManifestScript {
@@ -139,7 +140,6 @@ fn scaffold_manifest(slug: &str, name: &str) -> Manifest {
triggers: crate::manifest::ManifestTriggers::default(),
secrets: crate::manifest::ManifestSecrets::default(),
vars: std::collections::BTreeMap::new(),
extension_points: Vec::new(),
}
}

View File

@@ -161,7 +161,7 @@ pub fn build_bundle(manifest: &Manifest, base_dir: &Path) -> Result<Value> {
"triggers": triggers,
"secrets": manifest.secrets.names,
"vars": vars,
"extension_points": manifest.extension_points,
"extension_points": manifest.extension_points(),
}))
}

View File

@@ -224,6 +224,7 @@ pub async fn run(app_ident: &str, dir: &Path, force: bool, mode: OutputMode) ->
slug: app.app.slug.clone(),
name: app.app.name.clone(),
description: app.app.description.clone(),
extension_points,
}),
group: None,
scripts: manifest_scripts,
@@ -233,7 +234,6 @@ pub async fn run(app_ident: &str, dir: &Path, force: bool, mode: OutputMode) ->
names: secrets.iter().map(|s| s.name.clone()).collect(),
},
vars: manifest_vars,
extension_points,
};
std::fs::write(&manifest_path, manifest.to_toml()?)