Skip to content

Update never refreshes the shared package.json, and OverlaySystem does not check that it is the payload's own copy #2518

Open

Description

@drpaulobernardy

What happened

Two related gaps in the update path, both read in the 8.761.0 tag (not run):

  1. The shared runtime manifest <configRoot>/package.json is written once at install (DeployCore.ts:248-262, copyMissing) and never again. OverlaySystem refreshes SYSTEM_FILES (OverlaySystem.ts:90-104) and runs bun install only for nested manifests (:732, deployNestedDependencies, which walks LIFEOS/ and skills/). The upgrade chain in InstallAll.ts:225-236 does not include DeployCore. So if a release adds or bumps a dependency in install/package.json, an existing install keeps the old manifest and the hooks and TOOLS that import the new package fail with "Cannot find package" until someone edits the file by hand. Today the manifest holds only yaml, so nothing breaks yet; the failure is latent.

  2. OverlaySystem does not check that the script that is running is the one that ships in the payload it is overlaying. main() (:664-667) takes --skill-root and reads <skillRoot>/install, but the tree list (SYSTEM_TREES, imported at :54) and the file list (SYSTEM_FILES, :90) come from the running copy. Running an older or different copy against a newer payload refreshes the new payload with the old lists: a folder the new version adds is silently not overlaid. The documented route (InstallAll.ts:225, which runs <skillRoot>/Tools/OverlaySystem.ts with that same --skill-root) is consistent, so this only bites direct invocations. Question: do you want the guard?

Suggestion

  1. Add the manifest to SYSTEM_FILES with backup-first, as settings.system.json already is (:98), and have the overlay run bun install in <configRoot> when the file changed (the report already has a nestedDeps slot for this kind of line):

    ["package.json", "package.json", true],
    

    The payload's skills/LifeOS/install/package.json copy would need to stay in step.

  2. Refuse when the copy that runs is not the payload's, with a message that prints the command to run instead:

    const codeRoot = resolve(import.meta.dir, "../../..");
    if (resolve(payloadInstall) !== codeRoot) {
      console.log(JSON.stringify({ ok: false, refused: "not-from-payload", detail: `...run: bun ${join(payloadInstall, "skills/LifeOS/Tools/OverlaySystem.ts")} --skill-root ${skillRoot} --config-root ${configRoot}` }));
      process.exit(2);
    }
    

We carry both changes as local patches. Test idea: overlay with a payload that changes package.json and assert the file is replaced and a backup exists; invoke the script from a path that is not <payload>/skills/LifeOS/Tools/ and assert exit 2.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions