Skip to content

[OMEGA-430] Abort omega launcher start when script and Docker image versions differ - #364

Open
janaina-senna wants to merge 10 commits into
singnet:mainfrom
janaina-senna:jn/feat/omega-script-check-version
Open

janaina-senna wants to merge 10 commits into
singnet:mainfrom
janaina-senna:jn/feat/omega-script-check-version

Conversation

@janaina-senna

@janaina-senna janaina-senna commented Sep 24, 2026 •

Copy link
Copy Markdown

Description

Abort scripts/omega start (and the interactive bootstrap) when the host launcher version and the Docker image version are both known and do not match.

The check runs after docker pull and before docker rm -f omega. Host version comes from omega_version(); which returns the bare git describe --tags --dirty --always string, or an empty string when unknown. The image version is read from Omega/version, written at image build. If that file is empty, the same function runs inside the image with python3 -c. A trailing -dirty suffix is ignored, so a locally dirty checkout of the same tag is not a false mismatch.

If either version is empty (typical curl | bash, with no git metadata), the script warns and continues, so the documented pipe-install path still works.

The README now states that the launcher and image must be the same git tag.

How Has This Been Tested?

  • bash -n scripts/omega
  • ./scripts/omega --version
  • Launcher tests in tests/test_omegaclaw_launcher.py:
    • A matching image version allows start and still issues docker rm / docker run.
    • A mismatched image version exits non-zero, prints the mismatch message, and does not replace the existing container.
  • Existing launcher option tests still pass (component import flags, mutually exclusive flags, rejected removed flags).

Checklist

  • PR contains autogenerated code
  • Self-review completed
  • Test scenarios above are passed with the version of the code from PR

@janaina-senna janaina-senna changed the title Jn/feat/omega script check version Abort omega launcher start when script and Docker image versions differ Sep 24, 2026
@janaina-senna

janaina-senna commented Sep 25, 2026 •

Copy link
Copy Markdown
Author

Manual test of the matching scenario:

$ ./scripts/omega start -p Test -t test -d omega:dev
omega
a260a18972e5e5ecf485849de973a8d526fdb3d126fb376586f5b842aee56894
$ echo "exit: $?"
exit: 0

Manual test of the mismatching scenario:

$ ./scripts/omega start -p Test -t test -d omega:mismatch
The launcher script and Docker image versions do not match.
  Script: Omega version=v0.1.19-139-gb25ec74
  Image (omega:mismatch): Omega version=v0.0.0-test

Update the script or the image so both are the same tag/commit. For example:
  curl -fsSL https://github.com/singnet/Omega/raw/refs/tags/<tag>/scripts/omega | bash -s -- singularitynet/omega:<tag>
$ echo "exit: $?"
exit: 1

@janaina-senna

janaina-senna commented Sep 25, 2026 •

Copy link
Copy Markdown
Author

Unit tests for matching and mismatching scenarios were added:

$ pytest tests/test_omegaclaw_launcher.py -q
.......                                                                                                                                                    [100%]
7 passed in 1.60s

@vsbogd vsbogd left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea is right, but there is the excessive complexity in processing Omega versions. The problem is that instead of use bare version the code gets something like "Omega version ...." and tries to figure out version from this string. I would suggest get bare version from Python function instead.

Next question is what function to use. The function returning Omega version is

def omega_version(repo_root: str | os.PathLike | None = None) -> str:
But it returns already formatted string "Omega ..." which is not what we would expect. We need to split this function on two:

  • one returns bare version or empty string
  • another returns the formatted version if it is needed (personally I would not format version here at all and format it in the code which prints/sends the version instead)

Then we can get bare version using python -c ... command and postprocessing is not needed, code will be simpler overall.

@janaina-senna janaina-senna changed the title Abort omega launcher start when script and Docker image versions differ [OMEGA-430] Abort omega launcher start when script and Docker image versions differ Sep 25, 2026
@janaina-senna

janaina-senna commented Sep 29, 2026 •

Copy link
Copy Markdown
Author

Manual mismatch check with a local image:

Scenario: Create a new image based on an existing one, such as omega:dev, and write a different value to Omega/version. There’s no need to rebuild the entire image.

docker build -t omega:mismatch - <<'EOF'
FROM omega:dev
USER root
RUN chmod u+w /PeTTa/repos/Omega/version \
 && printf '%s\n' 'v0.0.0-test' > /PeTTa/repos/Omega/version \
 && chmod 0444 /PeTTa/repos/Omega/version
EOF

TEST_SERVER_IP=127.0.0.1 ./scripts/omega start -p Test -t test -d omega:mismatch

The command exits 1 and prints the mismatch message, with the host git describe version and Omega version=v0.0.0-test for omega:mismatch. It does not replace the existing container. omega:dev is any local image from this checkout; the extra build only replaces Omega/version.

Output:

$ TEST_SERVER_IP=127.0.0.1 ./scripts/omega start -p Test -t test -d omega:mismatch
The launcher script and Docker image versions do not match.
  Script: Omega version=v0.1.19-146-g8ee46cc
  Image (omega:mismatch): Omega version=v0.0.0-test

Update the script or the image so both are the same tag/commit. For example:
  curl -fsSL https://github.com/singnet/Omega/raw/refs/tags/<tag>/scripts/omega | bash -s -- singularitynet/omega:<tag>
$ echo $?
1

Comment thread src/helper.py
if version is not None:
version = result.stdout.strip()
if version:
return version

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@janaina-senna Is the bare version format intended for all existing omega_version() consumers? In particular, the MeTTa (version) skill and memory-export metadata now receive v… instead of the previous Omega version=v… format.
If not, should display-facing call sites format the value explicitly?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

omega_version() is meant to return the bare version, or an empty string, for every caller. That follows @vsbogd's review: keep the bare value in the function, and add the Omega version= prefix only where the version is printed.

The launcher does that for --version and for the mismatch message, which keeps the existing Omega version=$(git describe …) output. The MeTTa (version) skill calls omega_version() directly, so it now returns the version number (v…). Memory export stores that same bare string in OMEGA_VERSION. Neither of those sites adds the prefix.

@jazzbox35 jazzbox35 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved -- next step should be QA

Comment thread README.md Outdated
@TossSky

TossSky commented Oct 1, 2026

Copy link
Copy Markdown
Collaborator

Tested: image built from this PR at 8ee46cc (v0.1.20-5-g8ee46cc), started by scripts/omega from a clone at the same commit with -p Test -t test, through curl ... | bash and through the interactive bootstrap. For comparison I used singularitynet/omega:latest (on 2026-09-30 the same digest as v0.1.19), an image built without this change, an image built from git archive of 8ee46cc, and copies of the PR image with a different or an empty version file.

What I checked

  • With the clone and the image at the same commit, start and the interactive bootstrap go through without a warning, and so does a clone with local edits (v0.1.20-5-g8ee46cc-dirty).
  • With a different version in the image, start exits with code 1 and prints the mismatch, and the running omega container keeps its id and start time. The bootstrap from a clone also exits with code 1 and leaves the running container alone. The launcher on main starts such an image.
  • The two new launcher tests pass in CI.

Images up to v0.1.19 are never checked

scripts/omega:550-560 looks for the version only under /PeTTa/repos/Omega, while v0.1.19 keeps the version file in /PeTTa/repos/OmegaClaw-Core. With the default image, ./scripts/omega start prints "Could not determine the Docker image version; skipping version check." and replaces the running container. The new container then exits on startup with FileNotFoundError: [Errno 2] No such file or directory: '/PeTTa/repos/Omega/profile/policy.yaml'.

Without a version of its own the launcher skips the check

Piped into bash the way the README installs Omega, curl ... | bash -s -- <image>, the launcher has no version. From a directory whose parent has no src/helper.py, both the bootstrap and start print "Could not determine the launcher script version; skipping version check." and then run an image with a different version. The README paragraph says the bootstrap aborts in that case, and its example uses scripts/omega from v0.1.19, which ships only scripts/omegaclaw.

The same happens in a clone when python3 is Python 3.9. Importing src.helper fails with a TypeError at src/logger.py:28, so ./scripts/omega --version prints "Omega unknown" and start skips the check.

The piped launcher runs src/helper.py from above the current directory

In the piped mode, scripts/omega:520-530 takes the parent of the current directory as the checkout and imports src/helper.py from there. On start, the piped launcher imported and ran a src/helper.py placed one level above the current directory, while the launcher on main imports nothing on start. Run from the scripts directory of a clone of main, it reported "Script: Omega version=Omega version=v0.1.20" and refused the image built from this change, although that image matches the piped script.

Memory export fails when the version is unknown

omega_version() now returns an empty string when the version is unknown, and memory export writes it into the archive. An image built from git archive, which has no .git, gets an empty version file, and memory export in that image fails with ArchiveValidationError: Manifest source.omega_version is required. With src/helper.py from main, export from an image with an empty version file works and records "Omega unknown".

Two smaller issues. With an image built without this change, the mismatch line repeats the prefix: "Omega version=Omega version=v0.1.19-141-g81a2882". The bootstrap from a clone asks all eight questions, the LLM token among them, before it checks the image.

Verdict: FAIL
@janaina-senna @vsbogd @timur-ashkenov @jazzbox35

@janaina-senna

janaina-senna commented Oct 7, 2026 •

Copy link
Copy Markdown
Author

The piped installer cannot see the URL it was downloaded from, and it has no git checkout, so a command like

curl -fsSL https://github.com/singnet/Omega/raw/refs/tags/v0.1.21/scripts/omega | bash -s -- singularitynet/omega:v0.1.20

only warns and still starts the image. Should we record the release version inside scripts/omega, so that in this case the existing check can read the image version and abort when it is not the same, in this case not v0.1.21?
A git checkout would keep using git describe.

cc: @vsbogd

@vsbogd

vsbogd commented Oct 7, 2026

Copy link
Copy Markdown
Member

Should we record the release version inside scripts/omega, so that in this case the existing check can read the image version and abort when it is not the same, in this case not v0.1.21

We don't have any version imprinting into the files from the repository during release step at the moment. I don't see an easy way of adding it. When release is created via GitHub Release screen the release job is called after the tag is created. Thus there is no way to commit the release version under the same tag. The only way I think is publishing start script separately (out of GitHub repository or may be in a dedicated branch of the repository) and imprint version during such publishing. This requires changes in CI job.

@vsbogd

vsbogd commented Oct 8, 2026 •

Copy link
Copy Markdown
Member

The only way I think is publishing start script separately (out of GitHub repository or may be in a dedicated branch of the repository) and imprint version during such publishing. This requires changes in CI job.

Thus we in theory can add the dedicated branch (let's say singnet/Omega/start-script) and change release job to commit new script into it. But I am not sure if the result is worth the effort. I would rather move to the single start script approach if there is no issue found on review.

@janaina-senna

janaina-senna commented Oct 8, 2026 •

Copy link
Copy Markdown
Author

@TossSky Ready for review.

@TossSky

TossSky commented Oct 11, 2026

Copy link
Copy Markdown
Collaborator

Tested: 9cdcbfe (v0.1.20-11-g9cdcbfe). scripts/omega start -p Test -t test from a clone, a shallow clone and curl ... | bash, and the interactive bootstrap from a clone and curl ... | bash. Images: one built from 9cdcbfe, the published v0.1.20, and images with a different version, an empty version file, the v0.1.19 layout and the format from before this change.
088eaa4 only merges main and leaves the launcher, README and Dockerfile as tested.

What I checked

  • An image of the same version starts without a warning, including the published v0.1.20, with -d and by default. A clone with local edits (-dirty) is accepted.
  • With a different version, start exits with code 1, and the running omega container keeps its id and start time. This covers OmegaClaw version=v0.1.19 in /PeTTa/repos/OmegaClaw-Core/version and Omega version=v0.1.19-141-g81a2882, and each version is printed once.
  • The interactive bootstrap from a clone exits with code 1 before the first question.
  • curl ... | bash prints "Could not determine the launcher script version; skipping version check." and starts the image, as the README says. The piped launcher no longer imports src/helper.py from the parent directory.
  • With an empty version file, omega_version() returns unknown, and memory export and import work.

The same commit is refused when git describe prints a different string

scripts/omega:646 compares the git describe --tags --dirty --always output with the version in the image as plain strings. With core.abbrev=12, a clone at 9cdcbfe reports v0.1.20-11-g9cdcbfe705ea, and start refuses the image built from the same commit, which has v0.1.20-11-g9cdcbfe. A --depth 1 clone of 9cdcbfe has no tags, reports 9cdcbfe, and is refused too. Release tags are not affected: at a tag git describe prints just the tag, and the published image starts. This does not block the change.

Verdict: PASS
@janaina-senna @vsbogd @timur-ashkenov @jazzbox35

@TossSky TossSky left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

QA Approved!

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants