Commit Graph

2 Commits

Author SHA1 Message Date
ms-lead-reviewer
ac44a1aea7 fix(mosaic): resolve lease-activation CLI via exported "." entry, not "./package.json" (#869 C1 review fix)
Some checks failed
ci/woodpecker/pr/ci Pipeline failed
Independent review of PR #870 found defaultCapabilityProbe() resolved the
installed CLI via req.resolve('@mosaicstack/mosaic/package.json') — a
subpath NOT present in package.json's `exports` map. Node throws
ERR_PACKAGE_PATH_NOT_EXPORTED for that on every real install, which the
catch-all silently turned into an always-null probe: leaseEnforcementActivatable()
could never return true anywhere, defeating the card's purpose.

Fix: resolve via the already-exported "." entry instead
(require.resolve('@mosaicstack/mosaic') -> dist/index.js), then take
cli.js as its sibling in the same built dist/ directory — matching
package.json's bin.mosaic mapping. No change to the exports map itself
(that would mask a separate, out-of-scope pre-existing issue in
resolveTool()/launch.ts per review guidance).

Adds a positive-path test that stages a realistic fake dist/index.js +
dist/cli.js at the package's real resolved location and asserts
defaultCapabilityProbe() returns the actual {name, version} capability
object with zero mocking of the resolver. Verified red against the prior
(reverted-and-restored) buggy resolution before landing the fix, and green
after — the previous only-unmocked test asserted null for the wrong
reason (masking this bug) and is left in place alongside the new one.

Re-verified: launch.spec.ts (30), fail-closed-regression.spec.ts (2), and
runtime_tools_unittest.py (25, including both C-REGRESS-locked fail-closed
cases) all still green. typecheck/lint/format:check pass via
`turbo run ... --filter=@mosaicstack/mosaic`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-22 13:57:17 -05:00
ms-lead-reviewer
763cecc381 feat(mosaic): leaseEnforcementActivatable() capability probe (#869 C1)
Adds a real activation-capability probe so a downstream install-ordering
guard (C2, out of scope here) can refuse to wire lease-broker enforcement
(PreToolUse/Stop hooks) on a host that cannot actually activate it — the
root cause of #828's version-skew brick, where the published CLI tarball
lagged the enforcement reseed and every tool call denied with
GATE_UNAVAILABLE.

- LEASE_ACTIVATION_CAPABILITY {name, version}: versioned signal owned by
  the activation half (execLeaseGatedRuntime), independent of npm semver.
- Hidden `mosaic __lease-capability` subcommand: prints that capability
  from the actually-resolvable built CLI artifact, not source-tree
  presence.
- leaseEnforcementActivatable(): pure predicate, true iff a compatible
  capability is advertised AND the broker supervisor (launcher + daemon.py
  artifacts, socket path) resolves. Detection only — never starts the
  broker. Both inputs are injectable for testing.
- C-REGRESS: added a vitest spec that runs the two test-locked fail-closed
  gate cases in runtime_tools_unittest.py directly, proving the gate's
  fail-closed-on-absent-identity behavior is unchanged by this card.

Part of #869 (Point-1 C1).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-22 13:36:29 -05:00