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:
@@ -552,9 +552,21 @@ trust inversion). The rule:
|
||||
> site; the `PicloudModuleResolver` reads the importing node from Rhai's `_source` (set to each module's
|
||||
> owner via `AST::set_source(encode(owner))` before `eval_ast_as_new` — the lexical chaining), and the
|
||||
> cache is re-keyed by resolved `ScriptId`. Group modules + group-script imports are now allowed
|
||||
> (`group_scripts_api`), and the single-node apply runs the §5.5 dangling-import `plan` check. **Opt-in
|
||||
> extension points** (the dynamic-resolution branch + `[extension_points]` manifest declaration) remain
|
||||
> the one deferred piece of §5.5 — a clean additive follow-up on top of the now-origin-aware resolver.
|
||||
> (`group_scripts_api`), and the single-node apply runs the §5.5 dangling-import `plan` check.
|
||||
|
||||
> **Resolved (extension points ✅) — §5.5 is complete.** Opt-in polymorphism shipped: an extension
|
||||
> point is a **pure marker** `(owner, name)` (migration 0051 `extension_points`, owner-polymorphic +
|
||||
> CASCADE — structurally a `secrets` name), authored declaratively as an `[app]`/`[group]` manifest key
|
||||
> `extension_points = [...]` (a *node key*, so TOML can't mis-nest it); the optional **default body is a
|
||||
> co-located `kind=module` script**. The resolver's `ModuleSource::resolve_policy(origin, app, name)`
|
||||
> applies **nearest-declaration-kind-wins** over the importing node's chain (one query: min EP depth vs
|
||||
> min module depth, EP wins a tie): a concrete module → lexical; an EP marker → **dynamic**, resolved
|
||||
> against the inheriting app (its override, else the default body up-chain) — `NoProvider` is a hard
|
||||
> error. Reconcile mirrors `secrets` (name-only diff/prune/state-token); the single-node apply adds the
|
||||
> **no-provider `plan` check** (every EP visible to an app must have a provider); read-only
|
||||
> `pic extension-points ls` + `pull` round-trip complete the surface. **Authoring is declarative only**
|
||||
> (no imperative `add/rm`). Verified e2e: a group default resolves for an inheriting app, and the app
|
||||
> can **override** it — the deliberate inverse of the Phase 4b sealed/lexical import.
|
||||
|
||||
### 5.6 Tree lifecycle: delete, reparent, rename
|
||||
|
||||
|
||||
Reference in New Issue
Block a user