fix(goal): quiet waits and unify fleet NG ownership (#56, #57, #58)

This commit is contained in:
Dewey
2026-09-06 04:07:09 -05:00
parent 7345f330fc
commit 9a5fbdbda7
14 changed files with 892 additions and 26 deletions
@@ -0,0 +1,57 @@
# Fleet goal ownership
## Authority and acceptance
Jason confirmed Resume's NG footer and Alt+G, authorized fleet-wide correction, and authorized scoped commits after green suites. Joe/Huey quiet waits are "looking good so far", not final acceptance. Dewey owns this bounded work in mosaic-stack-dev-test. Independent read-only Pi review must approve exact source and deployment pins. CURRENT and the foundation work remain darkwing's.
Outcome: one shared NG implementation at ~/.mosaic/.pi/extensions/goal for existing fleet launch configurations, without duplicate registration. Retain wrapper-guard or mosaic-core role enforcement as configured, and the launcher's unslop hook. Remove the Resume-specific no-discovery override once ordinary discovery works. No automatic restarts, credentials/configuration edits, private-state reads, state migration, policy changes, or push. Local-first deployment remains the operator-authorized workflow; repository CI runners remain deferred, not reported green.
## Measured ownership
41 agent settings paths and 14 role settings paths reference fleet/extensions/goal. They resolve to 24 ordinary settings files; many agent settings are symlinks to role settings. All declared packages lists are empty. Most seat workdirs are the shared brain; Topher and Velma use their seat directories. Topher's extension directory and fifteen role extension links already resolve to shared extensions. Velma still has an ordinary standalone goal tree. The settings template also references fleet/extensions/goal.
Pi 0.85.1 package-manager toResolvedPaths canonicalizes resource paths before deduplication. We will verify this mechanism in the native loader with normal discovery enabled. Replacing settings would needlessly touch 24 files and still leave compatibility entrypoints. Instead, preserve every settings file/link and make the legacy fleet goal path and Velma standalone goal path compatibility symlinks to the shared NG goal. Keep their old ordinary source trees in verified backups. No recursive library forwarding and no separately auto-discovered core entrypoint are introduced.
## State boundary
The shared implementation resolves its NG state directory relative to the selected import path. Native fixture writes proved Pi deduplicates real source paths but Jiti retains the selected alias when resolving imports. At the brain cwd, state is ~/.mosaic/.pi/state/goal. At Topher or Velma's cwd, their project alias selects their own .pi/state/goal. A role cwd behaves the same way. With no project discovery, the legacy compatibility alias selects ~/.mosaic/fleet/state/goal. Every filename remains goal-state.<incarnation>.json. Do not claim all aliases use one state directory.
Legacy agent-home goal state remains untouched. Velma and Topher's existing NG stores remain in place. Source unification does not adopt, resume, delete or migrate existing goals. Existing processes keep their loaded code until the operator safely restarts them. Old goal evidence stays in its original location; do not assume an active goal will transfer. Native fixtures use fresh owned incarnation IDs and clean only their exact fixture files. Live canaries never invoke goal commands or read private state.
The first Velma synthetic fixture failed because it omitted Velma's existing neighboring mosaic-core libraries. The corrected fixture includes those libraries. All shared supporting modules match both installed legacy and Velma libraries byte-for-byte. Pin these dependency trees, wrapper and unslop entrypoints as well as the goal sources, since an alias does not redirect neighboring imports.
## Delivery
1. Pin all three source trees, the current Resume-hotfix launcher, and settings references/link targets. Pin launch.env filesystem identity/change metadata only. Environment files may contain credentials, so the deployment tool must never read or copy their contents. Register an issue and append session/build records.
2. Add an incident-scoped, fail-closed deployment tool and synthetic tests. Default is preflight. Stage two compatibility symlinks outside discovery, then atomically exchange them with the two ordinary trees. Restore the exact original shared launcher as the third change. Check pins before every effect. On failure reverse verified exchanges; on drift refuse rollback. Retain backup receipts and support explicit verified rollback. Never rewrite a run record.
3. Native red control must reproduce the duplicate with ordinary separate trees. Green fixture must load one shared goal through ambient plus explicit aliases, including root, role-linked, Topher-linked, Velma-linked and isolated cwd cases. Preserve configured wrapper/core tool interception plus unslop. Verify NG footer/full recall against identical installed runtime sources. Test hostile drift, symlink/special-file refusals and partial-failure rollback.
4. Independently review exact candidate, hashes, tests, state limits and rollback. Deploy locally only after approval, then rerun actual fleet resource combinations with normal discovery. Do not invoke auth-seeding launchers or restart sessions for testing.
5. Run goal, native, package and five repository suites. Stage only our explicit files, inspect the index, commit with Dewey identity, verify the commit. Do not stage foundation/skill/task dirt or overwrite CURRENT. No push authorized by this commit request.
6. Record Resume acceptance and fleet deployment distinctly. Close #57 for accepted Resume correction when evidence is recorded. Quiet-wait #56 and fleet user acceptance remain open until explicitly accepted.
The first independent review requested removal of launch.env content hashing because environment files can contain credentials. The corrected candidate pins only filesystem metadata and includes tests that reject any attempted environment-content read and detect metadata drift. The rejected manifest remains historical evidence and was never deployed.
## Deployment checkpoint, 2026-09-06 09:02 UTC
Corrected independent review APPROVE: .pi/evidence/goal58/review-v2.log. Deployed the reviewed three-path transaction and verified all after-pins and backups. Legacy fleet goal and Velma goal are now compatibility symlinks to shared NG. The shared launcher is byte-identical to its original pre-workaround version, SHA256 9352feed0acf9d449c26c0556ba00aba1c65ded43d376930a39ff6b5cee21986. No Resume-specific no-discovery override remains.
Reviewed plan SHA256: 43eb7821a484796850e5e9352f51fe8a6cffb2fb9084769070f449b529a47220. Backup and recovery receipt: /home/jwoltje/.mosaic/.pi/goal-backups/goal58-5baaf9ff598644c6ae364b297e3c982a. Its planned.json contains the complete source, dependency and configuration pins. The former plan-v2.json was rejected and never deployed.
Native negative control and six unified fixture cases pass, including owned fixture writes proving the state paths above. Seventeen transaction controls cover rollback, partial interruption, source/config/dependency/mode drift, symlink/special-file refusal, concurrent-writer lock refusal and the environment-content no-read boundary. Post-install native loading passed all 55 actual agent/role settings combinations with their configured wrapper or core tool interception and unslop. No live goal command or model turn ran. Evidence: .pi/evidence/goal58/live-matrix.log. This verifies registration/discovery, not every role-policy decision at runtime.
All 71 goal tests, 18 package controls, native footer/full recall and timed/untimed waiting checks pass. Repository suites pass: config 24, task 90, release 14, conductor 17, auth 15. Whitespace and prose checks pass. Static TypeScript checking and remote CI remain unavailable/deferred, not certified by these tests.
Explicit rollback, only if current source, dependency, configuration and backup pins still match:
```sh
python3 scripts/unify-fleet-goal.py rollback \
--plan /home/jwoltje/.mosaic/.pi/goal-backups/goal58-5baaf9ff598644c6ae364b297e3c982a/planned.json \
--sha256 43eb7821a484796850e5e9352f51fe8a6cffb2fb9084769070f449b529a47220 \
--backup /home/jwoltje/.mosaic/.pi/goal-backups/goal58-5baaf9ff598644c6ae364b297e3c982a
```
Rollback restores both old source trees and the previously accepted Resume workaround. Do not overwrite later concurrent changes to force rollback.
User test: at a safe stopping point, restart another seat through its normal launch command. Expect one NG footer, full /goal and Alt+G recall, no duplicate-tool startup error, and the same configured safeguards. Do not overwrite an existing assignment with a test goal. Old legacy state does not transfer automatically. No session was restarted by Dewey. Resume UX is accepted; fleet rollout is ready for user test and #56 quiet-wait feedback is still preliminary.
Commit scope excludes CURRENT, foundation planning/reviews, unrelated skills/tasks, and the shared logs because they contain other-owner uncommitted entries. Our evidence/acceptance checkpoints are in these owned plans; shared append-only records remain on disk. MS58-DW-1 informational notice to darkwing returned rc=2, submission unconfirmed; no blind resend and no reply requested. Last verified index release remains MS55-DW-3; inspect the index and commit only explicit owned paths. No push authorized. Issue #58. Evidence directory: .pi/evidence/goal58/.
+49
View File
@@ -0,0 +1,49 @@
# Goal quiet waits
## Latest checkpoint, 2026-09-06 09:02 UTC
Jason reports Joe/Huey are "looking good so far" after reloads. This is preliminary positive quiet-wait feedback, not final acceptance. He accepted Resume's NG footer/full recall, authorized fleet ownership correction and scoped suite-gated local commits. #58 now makes the legacy fleet and Velma goal paths compatibility aliases to shared NG and removes the Resume-only workaround. See docs/plans/2026-09-06_fleet-goal-ownership.md for the explicit state-location and no-migration boundary. All 55 live settings/discovery combinations load one shared NG goal with configured guards. The seven-file quiet-wait patch still has its independently approved SHA256 d9caeb0c87e074196421a010e8a2de0968b3bb922010fa864ca2ec1f1902ef6b. Goal, native, package and five repository suites were rerun green. No existing session or private state was changed. #56 remains open for final quiet-wait acceptance; no polling or rearmed timer.
The deployment and authority descriptions below are historical checkpoints. #58 supersedes the three-independent-copy topology and the earlier absence of commit authority.
Owner request: fix the untimed goal-check loop observed in Joe on 2026-09-06. Author: Dewey. Baseline: 7345f330fc6bfae5aa1d896c78cfb7cbe62efbae. Darkwing owns foundation mapping; none of its files are in scope.
## Defect
An accepted untimed wait resets the check counter but does not suppress settle or startup injection. The old quiet-wait test explicitly expects that behavior. Joe's pane showed an accepted wait followed by a new check and a 190k-token cache-miss notice. This is a scheduling defect; a cooldown would merely reduce its frequency.
## Scope and acceptance
- Canonical extension source/tests under extensions/goal, plus this plan and append-only delivery logs.
- All accepted waits suspend automatic checks, independent of timeout configuration.
- Untimed waits create no timer. Unrelated incoming messages and reloads preserve the wait. The model reconciles relevance; the extension never evaluates nextCheck as code or treats incoming text as permission.
- Explicit resume may reconcile a waiting or paused goal once. It clears the old wait; another unresolved report returns to quiet waiting.
- Timed waits retain one deadline wake per goal/resume and their existing abort/readiness/delivery safeguards.
- Guard queued check dispatch against duplicate lifecycle events, without blocking genuine subsequent work or retaining stale dispatches across goal replacement.
- Preserve footer/full recall, completion, pause/blocked, fencing, report-policy and write-failure behavior.
- Verify red-before-green regressions, full extension and repository suites, native no-model checks, independent exact-candidate review, and safe local test installation.
## Delivery boundary
No live fleet files, private goal state, user goals, or sessions are modified during development. The active operator goal explicitly authorizes local-first deployment under ~/.mosaic after verification. Do not automatically resume Joe or reload other seats. Before deployment, compare the actual shared entrypoint and every independent active copy with the reviewed baseline, preserve their state location, pin the file set, save rollback copies and verify native loading. The legacy fleet/extensions copy is distinct from the current .mosaic/.pi/extensions target; do not replace it merely because it exists. No push, CI/merge claim or foundation implementation. This is the operator-requested local development/deployment path, not a published release.
## Tasks
1. Reproduce untimed settle/startup injection and record red tests.
2. Fix wait gating, explicit resume and dispatch deduplication; verify regressions.
3. Review and test the candidate, including fresh native installation.
4. Deploy the pinned candidate to verified current targets, verify symlink resolution and a no-model native canary using isolated fixture state. Report reload requirements without driving existing sessions. Owner acceptance cannot be inferred from tests.
Status: deployed on disk and native-verified; ready for operator reload and acceptance. Issue #56: https://git.mosaicstack.dev/mosaicstack/stack-v2/issues/56. Four red regressions reproduced the old behavior; 71 goal tests, 18 package controls, native Pi timed/untimed Waiting fixtures, and all five repository suites pass. Independent read-only Pi reviewer approved the exact seven-file source/test/documentation candidate at 2026-09-06 07:50 UTC; transcript /tmp/goal56-review.log. Static TypeScript compiler remains unavailable; no claim of static checking.
At 07:51 UTC, the shared .mosaic/.pi/extensions/goal entrypoint, state and settle files matched HEAD byte-for-byte before the fix. Fifteen role extension links resolve to the shared root; Topher links through interact. Velma has an ordinary independent copy whose three runtime files also match HEAD. Joe's running process has cwd ~/.mosaic and no explicit extension flags. A broad initial symlink scan encountered a denied backup subtree; the bounded active roles/agents extension scan completed. The scratch pi-goal-x experiment is not a current shared target. Initial symlink-only inspection was insufficient: a subsequent settings scan found 41 agent and 14 role settings files still referencing legacy fleet/extensions/goal, including Joe. That path therefore also requires the scheduling backport, preserving its distinct state location and widget UI.
Deployment gate, 2026-09-06 08:00 UTC: canonical 71 tests and staged legacy 67 tests pass. The first full legacy staging run had two ENOENT errors because its external-relative skill fixtures were absent; copying the existing canonical fixtures into the expected staging location resolved them without changing live skills. Shared/Velma have an older README and no fixture .gitattributes; runtime files match the baseline. These differences were diagnosed and the actual whole-file trees pinned rather than bypassing a drift refusal. Independent deployment/backport reviewer APPROVE: /tmp/goal56-deploy-review.log.
Pinned deployment input: .pi/evidence/goal56/deployment-pins.json, SHA256 08aec1a0ff7c70ce2a5e1b6831c8ec395a94a2bafe9ca1be9c7110a6b913935c. One-shot deployment script: .pi/evidence/goal56/deploy.py, SHA256 248ec09b534f067d296fc70f2ce50b11810c9927321a58205e860eb19b39684a. Preflight and an isolated atomic-exchange/rollback test passed. Deploy only these three ordinary goal directories; core, settings, symlinks and existing goal states remain untouched. Deployment completed by atomic exchange. Rollback trees and write-once receipts: /home/jwoltje/.mosaic/.pi/goal-backups/goal56-60590600f2c9420a881f1f4f0a5fc5cf. All three deployed trees match their approved after-pins; all three backups match before-pins. All fifteen role links and Topher's agent link resolve to the patched shared tree. Six native Pi RPC canaries loaded the three actual installed entrypoints, timed and untimed: exactly one explicitly selected /goal per isolated canary, zero automatic checks/model starts, and no fixture state changes. Provider credentials were not inherited. All owned fixture states were removed. This does not assert ambient multi-extension discovery is conflict-free, nor that already running sessions have reloaded.
At 2026-09-06 08:02:45 UTC the canonical source still matched the deployed shared/Velma candidate. Canonical working-tree patch: .pi/evidence/goal56/canonical.patch, SHA256 d9caeb0c87e074196421a010e8a2de0968b3bb922010fa864ca2ec1f1902ef6b. Source remains uncommitted; no new commit/push authority was inferred from the earlier baseline authorization. No existing process was interrupted, reloaded, resumed or given a replacement goal. The legacy fleet copy preserves its original store and UI; core, settings and links are unchanged.
Remaining user-facing gate: Jason chooses a safe idle session, runs /reload, and confirms an accepted untimed wait remains quiet. If the chosen goal is paused, resume only when its assignment is still authorized; /goal resume deliberately reconciles once. Do not set a test goal over another agent's assignment. A relevant input should permit verified progress; unrelated input should preserve waiting. This is a manual operator acceptance wait using incoming messages, not a polling watch or another timer. No reload or owner approval is inferred from the native canaries. #56 remains open until that confirmation. The extension's one bounded deadline wake arrived after the 08:06:21 UTC deadline with no operator confirmation or defect report in the conversation. Acceptance remains blocked; no timer was re-armed and no session was inspected, reloaded or resumed. Resume this task on explicit operator confirmation or a defect report.
Communication: darkwing closeout MS55-DW-3 confirms its baseline and released index; no reply requested. The separate fix notice returned rc=2 (delivery unconfirmed); no blind resend. The d4696d09-pinned map remains historical.
@@ -0,0 +1,27 @@
# Resume goal discovery repair
## Accepted outcome, 2026-09-06 09:02 UTC
Jason explicitly confirmed the NG footer and Alt+G full recall. The Resume-specific workaround was then superseded by the authorized fleet fix in #58. Normal discovery now selects the shared NG source through compatibility aliases; the common launcher is restored to its original version with unslop retained, and wrapper/core enforcement stays as configured. All 55 live settings/discovery combinations pass. No settings, credentials or private state were migrated. See docs/plans/2026-09-06_fleet-goal-ownership.md. Resume's accepted defect correction is ready for #57 closure after the scoped commit. Fleet rollout and quiet-wait acceptance remain separate gates.
## Earlier correction — 2026-09-06 08:34 UTC
Jason rejected the legacy selection below and explicitly directed use of the shared NG extension. Resume now selects ~/.mosaic/.pi/extensions/goal with wrapper-guard and unslop retained, exactly once. No state migration or private-state writes. Independent correction review APPROVE; native selected-resource checks verify NG Alt+G and both guards; 71 goal tests and native footer/full recall pass. Installed NG runtime matches tested canonical source. Deployed launcher SHA256 dd9e5ece5f1a86cc286027668560198bb7a44d2ab891f7b1ab4f89d7379ca0e6. Backup: ~/.mosaic/.pi/goal-backups/goal57-shared-4d95a698f4bb4544a0cb90aed5e887a3/launch-seat.sh. Evidence: .pi/evidence/goal57-shared/. Other seats remain unchanged. Restart Resume through its normal launch command when safe; /reload alone in an already running legacy-selected process does not replace its CLI extension selection. Awaiting user retry.
## Earlier repair — legacy selection rejected by owner
Jason requested repair after Resume launch failed with duplicate goal_report registration. Dewey owns this bounded hotfix; foundation/CURRENT and existing agent sessions remain untouched.
The real native loader reproduces the collision when project discovery and Resume's explicit legacy extension are both enabled. A global-settings exclusion of the project entrypoint was tested and failed: Pi applies project auto-discovery exclusions in project scope. No live settings were changed for that experiment.
Chosen repair: Resume-only explicit extension selection in the shared launcher. Retain its declared legacy goal and wrapper-guard with explicit -e arguments while disabling automatic extension discovery for this seat. The launcher's existing explicit unslop hook remains enabled. This is not bare pi -ne: all three existing safeguards are explicitly retained. Refuse if Resume's declared extension list/packages drift from the reviewed two-resource configuration, or if a selected entrypoint is missing. Preserve the legacy state location, all settings/credentials, and all other seats' launch behavior.
Scope: one bounded block in ~/.mosaic/fleet/bin/launch-seat.sh, a canonical native discovery regression script, this plan, and append-only logs. Do not change per-seat shim conventions, mutate private goals, alter credential refusals, migrate state, restart seats, or disable safeguards. Broad fleet source/state unification is not part of this targeted repair; other seats are not silently redirected between the shared and legacy goal stores.
Acceptance: native negative control reproduces the original combined-discovery error; repaired selection loads exactly one goal_report and /goal, retains wrapper tool interception and unslop extension, and produces no loader errors. Validate shell syntax, exact candidate independent review, an atomic backup/replace with drift refusal, and post-install discovery. Do not launch the real auth-seeding pipeline merely to test resource selection. User retries the unchanged Resume launch command for final acceptance.
Status at 2026-09-06 08:29:51 UTC: deployed, ready for Resume retry. Issue #57: https://git.mosaicstack.dev/mosaicstack/stack-v2/issues/57. Independent reviewer APPROVE (.pi/evidence/goal57/review.log). Nine isolated selection controls passed (valid config plus refusals for extension/package drift, invalid JSON, additional project settings/resources/core entrypoint, automatic user extension directory, missing wrapper). Huey's extracted launcher arguments were unchanged. Native negative control reproduced the original collision; post-install native resource loading proved exactly one legacy goal_report and /goal, registered wrapper tool interception, unslop loaded, and no loader errors. A separate real Pi RPC CLI process using the repaired three-extension arguments started successfully without credentials, sessions or model turns. All 71 goal tests still pass; shell syntax and whitespace checks pass.
Launcher before SHA256: 9352feed0acf9d449c26c0556ba00aba1c65ded43d376930a39ff6b5cee21986. Reviewed/deployed SHA256: 9f5c987bb745b8edb6c2093f0dc4990f48229c0e429fbf388feda040cb2bfacb. Verified backup: /home/jwoltje/.mosaic/.pi/goal-backups/goal57-45d15b9891ff4ef392961615abefc8e7/launch-seat.sh. Atomic replacement preserved mode and refused concurrent drift. Rollback requires matching that deployed hash before atomically restoring the verified before-file; do not overwrite another owner's later launcher changes.
Only Resume's launch path changes. Other fleet seats may still have the duplicate-source configuration; do not describe this as fleet-wide consolidation. Existing running sessions were not touched. No goal state, settings, credential files, per-seat shims, source extensions, or foundation files were edited. No commit/push authority inferred. Evidence: .pi/evidence/goal57/. User acceptance: retry ~/.mosaic/fleet/agents/resume/launch.sh normally, without manually adding -ne. The existing credential warning remains correct and fail-closed. #57 stays open pending that retry.