Repair native launcher skill rename and fail-closed regression coverage (#1498)

This commit is contained in:
2026-09-08 18:12:20 -05:00
parent 12ff5da7df
commit f3dce32088
9 changed files with 62 additions and 14 deletions
+4
View File
@@ -1882,3 +1882,7 @@ Filbert final aggregation APPROVED: 90 files at 3f8e765b plus two metadata units
## 2026-09-08 — #1497 owner accepted
Jason accepted the limited publication/planned-recovery outcome following the plain-language brief and directed Proceed. Gitea comment 25943 records scope; #1497 close returned state closed. Technical evidence remains source 29c1defe and reviewed closeout 10448e41, isolated committed-tree fixtures 5/5 passed. No final WUI/design, production-readiness, crash-recovery or exactly-once acceptance. Original failures and exclusions preserved. Deferred registry review alignment is the next action, not implementation or release of C1/ACT-1.
## 2026-09-08 — #1498 skill/launcher mismatch before correction
Owner authorized reviewed fix/commit/push without live restarts or deployment. Baseline 12ff5da7; offline launcher fixture exit 1 reproduced absent ms-agent-watch requirement. Replacement ms-watch and watch CLI exist; contract/ownership reconciliation and focused repair next. Other skills and private/WUI records excluded.
+2
View File
@@ -143,3 +143,5 @@ are never rewritten or removed; corrections are new entries.
- 2026-09-08 — darkwing for Filbert — PUB-REC-FILBERT-FINAL-1 APPROVED 92 exact publication units at manifest 3f8e765b; final-verdict receipt preserved. Published at 29c1defe29e5793022e1d3820b265bfc0f7f628a, committed-tree fixtures 5/5 passed, push and fresh origin/refactor identity verified. Upstream OFL whitespace preserved; authored-path whitespace check passes, full check does not. Raw/unreviewed drift remains local. Jason trial acceptance pending; no deployment.
- 2026-09-08 — darkwing — Jason accepted bounded #1497 publication/recovery trial after plain-language recommendation: "THAT is an executive brief. Proceed." Acceptance comment 25943 recorded, issue closed. Source 29c1defe and closeout 10448e41 remain unchanged; no WUI design or production acceptance. CURRENT returns to deferred registry review alignment only.
- 2026-09-08 — darkwing — #1498 owner goal skill/launcher mismatch: isolated Pi launcher fixtures reproduced failure, stale required ms-agent-watch path absent while ms-watch replacement exists. Plan docs/plans/2026-09-08_skill-launcher-mismatch.md; no live launch or deployment. Other work preserved.
@@ -0,0 +1,13 @@
# Skill/launcher mismatch repair (#1498)
Owner goal authorizes Darkwing to fix this mismatch through independent review, commit and push on refactor. No live restart, deployment, policy expansion or unrelated skill adoption. Baseline 12ff5da7df91f5343a59999af98b67518c15d6a4. Preserve unrelated WUI/private artifacts and new skills. Registry review is superseded for this assignment only.
Reproduced with node --test scripts/test-darkwing-launch.mjs: exit 1 because explicit ms-agent-watch skill is absent. Log /tmp/skill-launcher-baseline.log. Replacement skills/ms-watch/SKILL.md and tools/agent-watch/agent-watch.sh exist. Stale references also occur in communications and proactive skills. Do not restore the deleted skill to hide the mismatch or run a real launcher.
Next: inspect replacement against actual watch CLI and source provenance, make the smallest compatible reference/test repair, verify failure controls remain fail-closed. Independently review exact frozen candidate via Filbert, then selective commit/push and remote verification. Acceptance: offline fixtures green, correct explicit skill path, missing-skill refusal tested, docs match real capabilities, no live effects, unrelated bytes preserved. Any replacement-skill content changes stay limited to verified contract corrections; no timer will be armed for this task.
State: working. Issue #1498 created HTTP 201. No implementation or approval claimed yet. Goal lifecycle is owned by the active extension; this is task tracking, not another goal loop.
## Verified correction
Launcher now explicitly selects ms-watch; communications/proactive references match. Replacement skill documentation reconciled against the complete watch CLI: explicit repository sender, observable query side effects, real socket precedence, transport-only acknowledgement limits. Watch implementation itself unchanged. Added missing-ms-watch refusal controls for all three Pi agents and assertions for exact new skill path/absence of old path. Combined offline fixtures 5/5 passed, bash syntax and diff whitespace checks passed. No timers, real launchers or model calls. Next gate: independent frozen-candidate review before selective publication.
+9 -3
View File
@@ -7,9 +7,15 @@ update this file to the next action). No ambiguity, no re-planning.
## Next action
Review `docs/plans/2026-09-03_auth-provider-harness-registry.md` and reconcile
Gate 7 with later owner decisions and #53's workspace/session model. This is
registry review alignment only; no registry implementation is authorized.
Complete owner goal #1498: repair the skill/launcher mismatch through independent
review, selective commit and push. Plan: `docs/plans/2026-09-08_skill-launcher-mismatch.md`.
Local correction selects ms-watch, preserves missing-skill refusal and clarifies
watch transport limitations. Offline launcher fixtures 5/5 passed. Next gate is
independent frozen-candidate review. No live restart, timer arming or deployment.
Other new skills, private/WUI artifacts and held work remain untouched.
Registry review alignment is deferred behind this explicit owner goal; no registry
implementation is authorized.
Jason accepted the bounded #1497 publication/recovery trial following the plain-
language brief and said "Proceed." Issue #1497 is closed; acceptance receipt:
+1 -1
View File
@@ -74,7 +74,7 @@ for file in "${CONTEXT_FILES[@]}"; do
[ -f "$file" ] && [ -r "$file" ] && [ -s "$file" ] || fail "missing, unreadable or empty context: $file"
done
SKILLS=(ms-tools ms-file-read ms-file-write ms-conductor ms-communications
ms-agent-watch ms-sdlc ms-proactive-agent ms-goal ms-unslop)
ms-watch ms-sdlc ms-proactive-agent ms-goal ms-unslop)
SKILL_ARGS=()
for skill in "${SKILLS[@]}"; do
[ -s "$REPO/skills/$skill/SKILL.md" ] || fail "missing skill: $skill"
+11
View File
@@ -48,6 +48,15 @@ fs.writeFileSync('capture.json', JSON.stringify({args: process.argv.slice(2), ag
assert.match(direct.stdout, /configuration checks passed/);
assert.notEqual(launch('--auth account --check', false).status, 0);
assert.equal(existsSync(join(root, '.pi/state')), false);
const watchSkill = join(root, 'skills/ms-watch/SKILL.md');
const watchContent = readFileSync(watchSkill, 'utf8');
rmSync(watchSkill);
const missingSkill = launch('--check', false);
assert.notEqual(missingSkill.status, 0);
assert.match(missingSkill.stderr, /missing skill: ms-watch/);
assert.equal(existsSync(join(root, '.pi/state')), false);
assert.equal(existsSync(join(root, 'capture.json')), false);
writeFileSync(watchSkill, watchContent);
ok(launch());
let captured = JSON.parse(readFileSync(join(root, 'capture.json')));
assert.equal(captured.incarnation, undefined);
@@ -60,6 +69,8 @@ fs.writeFileSync('capture.json', JSON.stringify({args: process.argv.slice(2), ag
assert.ok(captured.args.includes('--no-context-files'));
assert.ok(captured.args.includes('--no-skills'));
assert.equal(captured.args.filter(arg => arg === '--skill').length, 10);
assert.ok(captured.args.includes(join(root, 'skills/ms-watch')));
assert.equal(captured.args.includes(join(root, 'skills/ms-agent-watch')), false);
assert.ok(captured.args[captured.args.indexOf('--tools') + 1].includes('goal_report'));
const firstPrompt = captured.args[captured.args.indexOf('--append-system-prompt') + 1];
const context = readFileSync(firstPrompt, 'utf8');
+1 -1
View File
@@ -71,7 +71,7 @@ Class honestly. Never downgrade a question you want answered to `terminal-log`.
Silence is not an ack. A refusal with a reason is recoverable; a guess is not.
4. No secrets. Messages land in scrollback, logs, and possibly comms daemons.
5. Waiting on a condition? Arm `agent-watch` on the condition, not a poll of a
colleague's pane. Waiting on a seat? Message them (see ms-agent-watch).
colleague's pane. Waiting on a seat? Message them (see ms-watch).
## Receiving
+1 -1
View File
@@ -113,7 +113,7 @@ file entry, or queued draft does not prove that another turn will occur.
- Use existing message delivery for another agent's response. Do not poll its private
files or pane. Use an available coordinator's timeout mechanism for overdue requests.
- Use ms-agent-watch only when installed, supported, and authorized, for external
- Use ms-watch only when installed, supported, and authorized, for external
conditions with no existing wake owner. Verify a known-false control and the actual
condition, distinguishing pending from errors; handle an already-met condition now.
Verify registration, bind to the exact resource/version and destination, and record
@@ -1,10 +1,10 @@
---
name: ms-agent-watch
name: ms-watch
description: Use for all instances where a watch, wait, or agentic status check is needed. This skill avoid the need for wait cycles and other methods used to wait for an action outcome.
disable-model-invocation: false
---
# ms-agent-watch — self-armed condition watches
# ms-watch — self-armed condition watches
One CLI call arms an isolated `systemd --user` transient timer per watch. Each
tick is a fresh, cgroup-isolated process; no loop, no script, no orphan. You
@@ -13,7 +13,8 @@ never `sleep`, never write a watch script, never background anything.
## Tool
```bash
tools/agent-watch/agent-watch.sh start \
MOSAIC_AGENT_SEND="/absolute/checkout/tools/tmux/agent-send.sh" \
/absolute/checkout/tools/agent-watch/agent-watch.sh start \
--name <lowercase-id> --session <your-tmux-session> \
[--socket <tmux-socket>] # REQUIRED for mosaic-fleet seats using tmux
--when '<shell command>' # exit 0 = met; quote it
@@ -26,6 +27,14 @@ agent-watch.sh log <name> # what it did and why
agent-watch.sh stop <name> # retire + clean state
```
Use the actual checkout path in place of `/absolute/checkout`. The CLI otherwise
uses a sender under `$HOME/.config/mosaic`, which may not be this repository's
reviewed transport. No timers or meta-watch are installed merely by loading this
skill. Live watch operations require assignment authority. `list` and `status`
can write stale-notice claims and send messages; they are not read-only probes.
The CLI's `status [--json]` returns 0 for clean, 3 for stale/dead meta-watch,
and 6 for an unreachable systemd user bus. Do not infer health from a failed query.
## Rules
1. **Name it for the thing watched** (`ci-pr1350-green`, `peer-orch-01-reply`),
@@ -39,8 +48,11 @@ agent-watch.sh stop <name> # retire + clean state
4. **Conditions are cron-style**: clean-ish environment, `cwd=$HOME`. Use
absolute paths. Do NOT rely on ambient credentials — resolve tokens through
the git credential helper or absolute service-credential paths.
5. **rc=2 delivery is DELIVERED** (text reached your pane as a draft — FLEET-COMMS
E7); the watcher never retries it. Real failures retry twice then retire loudly.
5. **Transport is not application acceptance.** The current watcher treats sender
exit 0 and 2 as terminal for retry purposes. Exit 0 means transport dispatched,
application acceptance unknown; exit 2 does not prove submission or receipt.
Its legacy `delivered` log wording is not an acknowledgement. Other sender
failures retry twice, then retire; do not add blind resends.
6. **A broken condition (exit ≠ 0/1) retires the watch** with a terminal-log
note. Check `log <name>` before re-arming — re-arming a broken condition
without fixing it just burns another timeout.
@@ -48,8 +60,8 @@ agent-watch.sh stop <name> # retire + clean state
each watch should correspond to one pending fact.
8. **Retire your watches** when the mission closes (`stop`). `list` shows
stale-state entries whose timer is gone; stop removes those too.
9. Fleet seats MUST pass `--socket mosaic-fleet` — the default is the default
socket and the delivery will not reach you.
9. Fleet seats MUST pass `--socket mosaic-fleet`. Socket selection is explicit
option, then MOSAIC_TMUX_SOCKET, then unique discovery; ambiguity refuses.
## When NOT to watch
@@ -65,5 +77,5 @@ agent-watch.sh stop <name> # retire + clean state
|---|---|
| `started watcher ...` then nothing, timer inactive | condition broke (exit ≠ 0/1) or timeout hit — `log <name>` says which |
| `[watch:x] ... timeout after Ns` | retired; re-arm only if still relevant |
| delivered (rc=2) in log | delivered as draft into your pane — go read the pane |
| delivered (rc=2) in log | legacy retry classification, not proof of receipt; reconcile through authorized records, not private-pane inspection |
| delivery failed rc=1 after 3 attempts | your session was gone; restart it, then re-arm |