Commit Graph

2 Commits

Author SHA1 Message Date
ethernet
1ec55baea8 refactor(dev): drop the activation demo; keep only the invariant tests
The demo was scaffolding, not repo content: nothing referenced it but a
docstring.

The tests were 12 against the repo's 1-2 invariant bar. Keep the two that fail
silently when inverted -- the sentinel reaching an exec'd child (the unexported
variable this change fixes) and the prologue's staleness gate, which inverted
either way costs a re-sync per run or a stale environment that looks fine. The
per-OS command pair stays because neither host can observe the other's string.
Dropped the exit-code/message restatement, the no-sentinel cold path, and the
demo-driven harness.
2026-09-16 23:45:47 -04:00
ethernet
53d757fe85 feat(dev): self-activating scripts with a stale-aware activation sentinel
Repo scripts assume the PM-activated environment, so running one without
activation fails much later with a confusing ImportError. Add the two halves
covering both invocation paths:

- scripts/_activation.py: require_activation() exits immediately, naming the
  exact command for the caller's shell (source ./activate on POSIX,
  . .\activate.ps1 on a native Windows host), before any heavy import.
- scripts/_hermes-python: the POSIX shebang target. `#!/usr/bin/env -S bash -c
  '...'` hands itself the target path through bash -c's $0, sources activate,
  then execs the interpreter on the same file -- so tracebacks and __file__
  still point at the real script and ./scripts/foo.py works from any cwd with
  no manual source.

__HERMES_ACTIVATED changes from a bare "1" to the installed-state file the
environment was composed against, so one value carries activation, which
checkout activated it, and a staleness stamp. The prologue compares that file
against uv.lock / pyproject.toml / pm/lock.json with the `-nt` builtin -- no
process spawn -- and re-activates once when the inherited environment predates
its inputs. pm rewrites that file only on a real sync, so the check settles
back to current rather than re-syncing on every run.

A legacy "1" keeps working: require_activation() tests non-emptiness, and the
prologue's [ -e ] fails on it, so it activates once and upgrades.
2026-09-16 19:32:07 -04:00