12. Update and extension lifecycle
A new project has no install step. familiar-workspace/ ships complete:
- the rules
- each agent’s own skills and subagents
- the empty content folders
- a filled-in
.familiar-project(created: not-yet-set)
You get a working project when you rename the folder and open an agent inside it. The first time
project-status → Check-in runs, it writes the real date into created and asks for a
Project Name (§4.1, §8.2). It also asks for a signature if the project has none, which
/ili-system-settings preferences can also set. No script sets up a project, and nothing is
compiled.
One script updates a project: .familiar/scripts/update.py. system-settings → Update runs it from
a session, so most users never open a terminal. You can also run it from a terminal (§12.1).
system-settings → Update (§5.4a) is the only route for updates. You start it yourself. It never
starts from a route match, because the whole system-settings menu is (user-only).
12.1 What Update does
Section titled “12.1 What Update does”Update runs the updater after your yes. references/update.md reads the project’s version from
.familiar/installed.json → core.version and from the marker. It reads the new release’s version
from its VERSION file. It also reads core.build from both installed.json files. A release
build writes into core.build the commit it came from, with -dirty if that commit had
uncommitted changes. The comparison works like this:
- A newer version is an update.
- The same version with a different build is also an update.
- If the build is missing, Update cannot decide. It reports that, and you choose.
Update then compares the state-schema lines, because a difference means a migration, which no
procedure performs. Then it runs the new release’s update.py against the project in report mode,
and explains the report. After your yes, it runs the updater with --apply and reads the result
back.
The release folder is one that you named, read for this task only (routes.md → Files outside the
project). The updater makes every write, and only inside the project. If the agent cannot run the
command, the branch gives it to you with both paths filled in. A project without
.familiar/release-manifests/familiar.json goes to the hand procedure in INSTALL.md → Updating. That
procedure starts a fresh folder, adds the extensions again, and moves the five content folders
across.
The updater. update.py runs from the new release’s copy against the project. It reads the
release and writes only to the project. It decides file by file against the project’s own release
manifests. There is one manifest per owner: familiar for core, and each extension under its own
ID. A release build writes each manifest with a fingerprint of every file it ships. Each file gets
one of these results:
same: the project’s copy matches the new release.update: the project’s copy still matches what the old release shipped, so replacing it loses nothing.diverged: the copy matches neither, so someone edited it. The updater leaves it alone and reports it.add: the file is new in this release.retired: the release no longer ships the file. An unedited copy moves into the update’s backup folder, with any folder that it leaves empty. A retired skill therefore stops loading, and nothing is lost (CORE-NO-DELETE). An edited copy stays in place, and stays in the manifest so that later runs keep reporting it.
The updater compares and replaces entry files only inside their familiar:start/familiar:end
block. It stops before any write in three cases:
- the schemas differ
- the project has no core manifest
- a release file does not match its own manifest
It updates an extension only from a folder named with --extension. It checks each installed
extension’s declared core range either way. Before --apply writes, it copies every file it will
replace, and the old marker, into 5-System/_update-backups/<old>-to-<new>_<date>/. Then it sets
only the familiar-version: line and runs project_check.py. Separate manifests for each owner, and
the check before each write, make an in-place update safe. A core update never touches an
extension’s package.
One hazard remains. Some files under 4-Trackers/, 3-Knowledge/ and 2-Drafts/ hold release text
beside project data, and the update does not change them. If a new release changes a format, those
files do not get the change until you look at them yourself. Update tells you to do this.
To remove an extension, delete the paths that its folder added, listed in its own _about.md. There
is no list to update as well. The files on disk are the record.
12.2 No Python at runtime
Section titled “12.2 No Python at runtime”Routing, skills and state are files that an agent reads directly, and setup needs no Python. The
updater (§12.1) is a standard-library Python script. The hand procedure needs no Python. Otherwise,
only the optional document and extraction scripts and the small read-only helpers under
.familiar/scripts/ use Python. The document scripts check their own dependencies with
--health-check and fall back as their skills describe. doctor.py (§9.5) reports on the whole
toolchain at once.