64 lines
4.9 KiB
Markdown
64 lines
4.9 KiB
Markdown
# #1194 — Installed framework-tool drift detection and refresh analysis
|
|
|
|
## Decision
|
|
|
|
The reported queue-guard source defect was already fixed on `main` by `58b971ab`; the live failure came from a stale `~/.config/mosaic/tools/git/ci-queue-wait.sh`. The durable fix is therefore a detector, not a duplicate queue-guard patch.
|
|
|
|
`mosaic doctor` now compares the framework tools bundled with the executing Mosaic package against the deployed tools tree. Doctor is the selected visibility boundary because it is observational and operator-invoked: unlike session start, it does not add a repository/network scan to every seat launch, and it cannot silently replace identity or messaging tools while seats are active. It reports drift without changing files. `--fail-on-warn` converts detected drift into a non-zero doctor result.
|
|
|
|
## Classification
|
|
|
|
The existing `framework-manifest.txt` is authoritative:
|
|
|
|
- Every source file under `tools/**` is framework-owned and required in the deployed tools tree.
|
|
- `tools/_lib/credentials.json` is explicitly operator-owned and excluded from byte comparison.
|
|
- A file present only in the deployed tools tree is operator-owned/unknown by the manifest's fail-safe default. The detector reports it as `INSTALLED_ONLY operator-or-unknown` but does not fail or delete it.
|
|
|
|
This means `NOT_INSTALLED` is not suppressed by filename guesses such as “test” or “README”: if it ships below source `tools/**`, the installer contract says it should be installed. Source-only implementation files outside `tools/**` are outside this detector population by construction.
|
|
|
|
## Current host analysis (observation only; no refresh performed)
|
|
|
|
A direct source-vs-installed census showed broad drift, including identity and messaging behavior:
|
|
|
|
- Identity/provider operations: stale `git/detect-platform.sh`, `issue-comment.sh`, `issue-create.sh`, `issue-close.sh`, `issue-view.sh`, `pr-create.sh`, `pr-merge.sh`, `pr-review.sh`, `pr-metadata.sh`; missing `pr-edit.sh` and several identity/read-back regression tools.
|
|
- Messaging/session: stale `tmux/agent-send.sh`, `tmux/send-message.sh`, their regressions, and `fleet/start-agent-session.sh`.
|
|
- Gate enforcement: stale `git/ci-queue-wait.sh`; missing the queue tri-state/process-level suites and terminal-green verifier.
|
|
- Lease/QA behavior: stale lease-broker launch/mutation/receipt tools and QA hooks.
|
|
|
|
Counts vary with source head and installed local/operator files; the detector prints measured counts every run rather than baking this snapshot into policy.
|
|
|
|
## Reviewed refresh command — analyse only, do not run during active seats
|
|
|
|
Use the package/release updater's manifest-driven keep-mode sync during a quiet maintenance window:
|
|
|
|
```bash
|
|
MOSAIC_SYNC_ONLY=1 \
|
|
MOSAIC_INSTALL_MODE=keep \
|
|
MOSAIC_HOME="$HOME/.config/mosaic" \
|
|
bash /path/to/reviewed/@mosaicstack/mosaic/framework/install.sh
|
|
```
|
|
|
|
For the globally installed package, resolve the reviewed installer rather than guessing its path:
|
|
|
|
```bash
|
|
PACKAGE_ROOT="$(dirname "$(node -p "require.resolve('@mosaicstack/mosaic/package.json')")")"
|
|
MOSAIC_SYNC_ONLY=1 MOSAIC_INSTALL_MODE=keep MOSAIC_HOME="$HOME/.config/mosaic" \
|
|
bash "$PACKAGE_ROOT/framework/install.sh"
|
|
```
|
|
|
|
Do not run this while agent seats are active: the stale set includes identity selection, provider mutation, messaging, queue/merge guards, lease enforcement, and session launch. Syncing those files in place can change behavior between a seat's preflight and mutation.
|
|
|
|
## Post-refresh verification
|
|
|
|
1. Run `mosaic doctor --fail-on-warn`; require `stale=0 not-installed=0` from the framework drift summary (other unrelated doctor warnings must also be adjudicated).
|
|
2. Re-run the constructed process-level queue probes against the **installed path**, not the source checkout. Use the source suite while overriding its subject path in a reviewed scratch copy, or reproduce these exact observations:
|
|
- pending provider payload: guard must print `state=pending`, print the pending context, wait, and exit non-zero/timeout — never return immediately with rc 0;
|
|
- malformed payload: guard must print `state=malformed` and exit non-zero;
|
|
- unsupported but valid status vocabulary: guard must print `state=unknown` and exit non-zero.
|
|
3. Run provider author read-back for one deliberately low-risk wrapper operation before resuming fleet mutation work; wrapper self-report is not identity evidence.
|
|
4. Relaunch seats only after the quiet-window verification, because existing processes retain loaded environment/context.
|
|
|
|
## Probe evidence
|
|
|
|
The detector regression constructs a stale installed tool plus a missing shipped tool and observes rc 1 with distinct `STALE` and `NOT_INSTALLED` lines. That case would pass or be invisible before this change because no installed-vs-shipped comparison existed. Controls prove byte-identical tools pass, the credential carve-out is ignored, installed-only paths are classified without deletion/failure, and comparing a tree to itself refuses with `CANNOT_ASSERT`.
|