Lesson 41 — The package lifecycle: both sides of a version
Goal: publish two versions as an author, install them as a consumer, keep an old pin, update, roll back, and update again. You play both roles on two branches of the same instance. The interactive lesson creates and removes its own branches, graphs, pins, versions and empty namespaces.
This follows Lesson 32 for the individual package actions. Lesson 23 and Lesson 24 cover contribution and review on this instance; the last section explains how a contribution travels from another organization or registry.
Two roles, two sibling branches
| Branch | Role | Holds |
|---|---|---|
tutorial-vendor |
Author | Source namespace tutorial-greetings |
tutorial-site |
Consumer | A pin on tutorial-greet and its own welcome graph |
Create both branches from main. Neither sees the other's later version
rows. Main stays unchanged. These branches belong to the lesson; do not
reuse an existing branch with either name.
Publish the first version
- Switch to
main, open the branch chip, entertutorial-vendor, and click Create. - Click New namespace, type
tutorial-greetings, and press Enter. On its row click + → New graph…, name itgreet, Enter. - On the new card choose set parent… →
core.logic.const. On:value, + → Bind literal, enter1, Save. - Hover
tutorial-greetings, click ⬆, enter package nametutorial-greetand version1.0.0, then Publish. Keep the release private: both roles use your current organization. - Close the publish form with ×.
A publication stores an immutable package version. Editing the source later changes neither that version nor any consumer's pin.
Install and build a consumer
- Switch to
main; createtutorial-sitefrom it. - Open packages → + Install a package and click Install
on
tutorial-greet 1.0.0. The branch gets a pin and the Explorer gainstutorial-greetings@1-0-0. Close the panel with ×. - Create namespace
tutorial-shopand graphwelcomewithin it. Set its parent tocore.strings.to-str. - On
:value, + → Bind fn-ref, typegreet, and choosetutorial-greetings@1-0-0.greet. - Select
tutorial-shop.welcome, click ▶ Run on its card, then Run in the Inspector. The displayed result is1, a string produced byto-str.
Reference or inherit? This consumer references the package graph
through a binding. A pin update rewrites its own references into the new
version's namespace. Had greet been its parent, the parent identity
would have stayed on that exact version. Use inheritance for an exact
parent; use a reference when the consumer should follow its pin.
See the parent-set identity decision.
Publish an edit, then follow it
- Switch to
tutorial-vendor; selecttutorial-greetings.greet. Change its bound:valueto2, Save. - Clear the Explorer filter if needed, hover the source namespace,
click ⬆, and publish
tutorial-greet 1.0.1. Close the form. - Switch to
tutorial-site; selecttutorial-shop.welcomeand run it again. It still returns1: publishing has not moved its pin. - Open packages. On the installed row enter
1.0.1and click ↑. Close the panel. Welcome's binding now points attutorial-greetings@1-0-1.greet; run it and read2. - Enter
1.0.0on that same installed row and click ↑. Its reference returns totutorial-greetings@1-0-0.greet; run it and read1. An update and a rollback use the same action. - Enter
1.0.1, ↑, and run once more:2.
A changed value with the same functions and argument types is compatible
with a patch release. Removing a function or narrowing an argument needs
a major release; the publish action checks compatibility before saving.
The version box also accepts latest and semver constraints, as explained
in Lesson 32.
The lesson checks three things separately: the saved branch pin, the
actual binding's referenced function UUID, and the current run's result.
A typed version, another graph called greet, or an old result alone
cannot complete these steps.
Finish and retry safely
Return to main, click Finish, then Delete created entities.
Cleanup first uninstalls this lesson's exact pin in tutorial-site, then
removes the sibling branches, its exact published versions, and its empty
namespaces. The lesson has no merge dependencies, so neither branch needs
to be archived. Deleting a branch alone does not remove its registry pin.
Creation receipts are saved before branch reloads. If a publish or install reply is lost, the lesson retains that pending item in Lessons for review and retry. It does not claim an existing version or namespace by name, and it does not withdraw other versions of the same package. Keep ends cleanup tracking and preserves your work deliberately.
On a real project, withdrawal removes a published version only when no
branch pins it; otherwise the action returns still-installed. The
organization's package install audit shows which branches still use it.
Uninstalling a pin does not itself withdraw the published version.
Contributing a fix
The interactive loop uses your own source. To fix a teammate's package on the same instance, branch from its source, compare the change, propose it and review it as in Lessons 23 and 24. Merging the source change still does not publish a new immutable version or move a consumer's pin.
If the source belongs to another organization or another Graphden, there is no author branch for you to edit. Fork copies a published version into your graph at its original namespace and writes no pin. Edit that copy and point your own binding at it. Fork refuses a namespace owned by a built-in package; that source must change on disk, as in Lesson 31.
Sending the fix back depends on access to the author:
| Author | Contribution |
|---|---|
| Teammate on this instance | Source branch and review, Lessons 23–24 |
| Reachable hub | Owner-stamped branch push and compare, Lesson 34 |
| Someone who can receive a file | An EDN bundle applied to a fresh review branch |
For example, the author can import a received bundle into a new branch:
curl -X POST "http://localhost:9002/api/import/graph?target=contrib/greet&create=true" \
-H "Authorization: Bearer $AUTH_TOKEN" \
-H "Content-Type: application/edn" \
--data-binary '{:fns [{:name :greet :namespace "tutorial-greetings"
:parent :const :args {:value 2}}]}'
Inspect the import's skipped-owned and adopted results, compare, and
review before merging. Import reports attempts to overwrite built-in
package functions instead of silently taking ownership of them. The
interactive lesson does not simulate a remote registry or a hub push.
The same version loop over HTTP
Set X-Graphden-Branch to the author or consumer branch for each request.
Publish, install, and update accept JSON bodies.
| Action | Request |
|---|---|
| Publish | POST /api/packages/publish with {"name":"tutorial-greet","version":"1.0.0","ns-root":"tutorial-greetings"} |
| Install | POST /api/packages/install with {"name":"tutorial-greet","version":"1.0.0"} |
| Update or rollback | POST /api/packages/update with the package name and target version |
| Uninstall | DELETE /api/packages/uninstall?name=tutorial-greet |
| Withdraw one version | DELETE /api/packages/withdraw?name=tutorial-greet&version=1.0.0 |
Install and update return the saved pin, version UUID/hash, and namespaces
created by that materialization. A repeated operation does not claim
existing namespaces. Uninstall and withdrawal optionally take an
expected-id query parameter: an identity mismatch refuses the operation
before removing anything. This protects cleanup from a same-name replacement.
When the roles belong to different parties
On the same cloud, another organization sees only a release published Public. Its consumer cannot edit your source, so it uses a fork to prepare a contribution. Another Graphden can pull a version through the remote-install form; its contribution travels as a hub push or EDN bundle. These are real external operations described in Lessons 31 and 34, not additional local fixtures created by this walkthrough.
Package dependencies must be present before installation. A package that reads secrets carries a manifest of arguments needing secret definitions; vault paths are stripped by default. The consumer defines those secrets in its own environment, as in Lesson 16. For ratings, metadata and install counts, see Lesson 40.
Next
Lesson 42 — AI clients and API tokens connects a coding client to the graph on a branch of its own. Package distribution documents the registry and its API in more detail.