@zerwiz/ymir 0.1.4 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/README.md +291 -0
- package/.agents/agents/bragi-marketer.md +111 -0
- package/.agents/agents/brokk.md +352 -0
- package/.agents/agents/forseti-reviewer.md +93 -0
- package/.agents/agents/frigg-consent.md +77 -0
- package/.agents/agents/groa-update.md +77 -0
- package/.agents/agents/hnoss-designer.md +69 -0
- package/.agents/agents/huginn-researcher.md +99 -0
- package/.agents/agents/jord-projects.md +78 -0
- package/.agents/agents/kvasir-scout.md +91 -0
- package/.agents/agents/mimir-planner.md +92 -0
- package/.agents/agents/muninn-stow.md +77 -0
- package/.agents/agents/saga-bearings.md +78 -0
- package/.agents/agents/sindri-developer.md +114 -0
- package/.agents/agents/snotra-documenter.md +105 -0
- package/.agents/agents/syn-recovery.md +78 -0
- package/.agents/agents/tyr-check.md +78 -0
- package/.agents/agents/urdh-hold.md +77 -0
- package/.agents/agents/volundr-smith.md +80 -0
- package/.agents/agents/vor-diagnostics.md +77 -0
- package/.agents/assets/agents/naming.md +50 -0
- package/.agents/assets/agents/registry.md +93 -0
- package/.agents/assets/agents/runtime.md +36 -0
- package/.agents/assets/agents/toon-tasks-cli.md +42 -0
- package/.agents/assets/templates/company_entity.template.md +37 -0
- package/.agents/backend/README.md +74 -0
- package/.agents/backend/backends/cmux.sh +649 -0
- package/.agents/backend/backends/herdr-eventwait.py +157 -0
- package/.agents/backend/backends/herdr-workspace-move.py +114 -0
- package/.agents/backend/backends/herdr.sh +3386 -0
- package/.agents/backend/backends/orca.sh +290 -0
- package/.agents/backend/backends/tmux.sh +357 -0
- package/.agents/backend/backends/zellij.sh +700 -0
- package/.agents/backend/fm-afk-launch.sh +654 -0
- package/.agents/backend/fm-afk-return.sh +241 -0
- package/.agents/backend/fm-afk-start.sh +172 -0
- package/.agents/backend/fm-arm-command-policy.mjs +960 -0
- package/.agents/backend/fm-arm-pretool-check.sh +200 -0
- package/.agents/backend/fm-backend-hometag-lib.sh +52 -0
- package/.agents/backend/fm-backend.sh +981 -0
- package/.agents/backend/fm-backlog-handoff.sh +909 -0
- package/.agents/backend/fm-backlog-receive.sh +187 -0
- package/.agents/backend/fm-backlog-transition-lib.sh +779 -0
- package/.agents/backend/fm-bearings-board.sh +204 -0
- package/.agents/backend/fm-bearings-snapshot.sh +546 -0
- package/.agents/backend/fm-bootstrap.sh +1568 -0
- package/.agents/backend/fm-branch-outcome.sh +203 -0
- package/.agents/backend/fm-branch-prompt.sh +101 -0
- package/.agents/backend/fm-brief.sh +452 -0
- package/.agents/backend/fm-busy-event.sh +234 -0
- package/.agents/backend/fm-busy-lib.sh +986 -0
- package/.agents/backend/fm-captain-hold.sh +1001 -0
- package/.agents/backend/fm-cd-command-policy.mjs +153 -0
- package/.agents/backend/fm-cd-pretool-check.sh +190 -0
- package/.agents/backend/fm-check-lib.sh +74 -0
- package/.agents/backend/fm-check-register.sh +42 -0
- package/.agents/backend/fm-check-unregister.sh +52 -0
- package/.agents/backend/fm-classify-lib.sh +1770 -0
- package/.agents/backend/fm-claude-stop-autoarm.sh +334 -0
- package/.agents/backend/fm-composer-lib.sh +1416 -0
- package/.agents/backend/fm-config-inherit-lib.sh +1202 -0
- package/.agents/backend/fm-config-push.sh +254 -0
- package/.agents/backend/fm-control-lib.sh +251 -0
- package/.agents/backend/fm-control.sh +878 -0
- package/.agents/backend/fm-crew-state.sh +625 -0
- package/.agents/backend/fm-cursor-lib.sh +243 -0
- package/.agents/backend/fm-decision-hold.sh +232 -0
- package/.agents/backend/fm-doc-audience-check.sh +269 -0
- package/.agents/backend/fm-dod-lib.sh +67 -0
- package/.agents/backend/fm-ensure-agents-md.sh +253 -0
- package/.agents/backend/fm-extension-launch-barrier.mjs +129 -0
- package/.agents/backend/fm-extension.mjs +2577 -0
- package/.agents/backend/fm-extension.sh +16 -0
- package/.agents/backend/fm-ff-lib.sh +420 -0
- package/.agents/backend/fm-fleet-snapshot.sh +1463 -0
- package/.agents/backend/fm-fleet-sync.sh +458 -0
- package/.agents/backend/fm-fleet-view.sh +96 -0
- package/.agents/backend/fm-gate-refuse-lib.sh +102 -0
- package/.agents/backend/fm-guard.sh +242 -0
- package/.agents/backend/fm-harness.sh +195 -0
- package/.agents/backend/fm-herdr-ci-cleanup.sh +115 -0
- package/.agents/backend/fm-herdr-lab.sh +346 -0
- package/.agents/backend/fm-herdr-session-cleanup.sh +337 -0
- package/.agents/backend/fm-home-seed.sh +984 -0
- package/.agents/backend/fm-home-summary-refresh.sh +255 -0
- package/.agents/backend/fm-hook-host-lib.sh +36 -0
- package/.agents/backend/fm-inactive-reconcile.sh +531 -0
- package/.agents/backend/fm-inbox.sh +399 -0
- package/.agents/backend/fm-install-actionlint.sh +84 -0
- package/.agents/backend/fm-install-herdr.sh +96 -0
- package/.agents/backend/fm-install-shellcheck.sh +84 -0
- package/.agents/backend/fm-install-treehouse.sh +95 -0
- package/.agents/backend/fm-kimi-turnend-hook.sh +276 -0
- package/.agents/backend/fm-lease-lib.sh +218 -0
- package/.agents/backend/fm-lease.sh +189 -0
- package/.agents/backend/fm-line-cap-lib.sh +51 -0
- package/.agents/backend/fm-lint-workflows.sh +137 -0
- package/.agents/backend/fm-lint.sh +591 -0
- package/.agents/backend/fm-lock-lib.sh +104 -0
- package/.agents/backend/fm-lock.sh +107 -0
- package/.agents/backend/fm-marker-lib.sh +12 -0
- package/.agents/backend/fm-merge-local.sh +74 -0
- package/.agents/backend/fm-merge-outcome-lib.sh +138 -0
- package/.agents/backend/fm-nm-run-lib.sh +124 -0
- package/.agents/backend/fm-on.sh +125 -0
- package/.agents/backend/fm-operational-input.sh +253 -0
- package/.agents/backend/fm-peek.sh +46 -0
- package/.agents/backend/fm-pending-reply-lib.sh +1409 -0
- package/.agents/backend/fm-pr-check.sh +135 -0
- package/.agents/backend/fm-pr-lib.sh +1016 -0
- package/.agents/backend/fm-pr-merge.sh +707 -0
- package/.agents/backend/fm-pr-poll.sh +110 -0
- package/.agents/backend/fm-primary-scope-lib.sh +33 -0
- package/.agents/backend/fm-procevent-extension-capture.pl +259 -0
- package/.agents/backend/fm-procevent-lavish.sh +628 -0
- package/.agents/backend/fm-procevent-lib.sh +892 -0
- package/.agents/backend/fm-procevent-quota.sh +290 -0
- package/.agents/backend/fm-procevent-remote-reply.sh +577 -0
- package/.agents/backend/fm-procevent-when.sh +504 -0
- package/.agents/backend/fm-procevent.sh +1466 -0
- package/.agents/backend/fm-project-mode.sh +92 -0
- package/.agents/backend/fm-project-origin-lib.sh +180 -0
- package/.agents/backend/fm-promote.sh +282 -0
- package/.agents/backend/fm-public-followup-emit.sh +260 -0
- package/.agents/backend/fm-public-followup-lib.sh +398 -0
- package/.agents/backend/fm-public-followup.sh +1330 -0
- package/.agents/backend/fm-push-transition-lib.sh +168 -0
- package/.agents/backend/fm-quota-axi-lib.sh +93 -0
- package/.agents/backend/fm-quota-choose.sh +384 -0
- package/.agents/backend/fm-remote-delta-read.sh +189 -0
- package/.agents/backend/fm-remote-doctor.sh +800 -0
- package/.agents/backend/fm-remote-entrypoint.sh +193 -0
- package/.agents/backend/fm-remote-file.sh +234 -0
- package/.agents/backend/fm-remote-home-provision.sh +259 -0
- package/.agents/backend/fm-remote-home-seed.sh +259 -0
- package/.agents/backend/fm-remote-inherit-push.sh +90 -0
- package/.agents/backend/fm-remote-inherit.sh +179 -0
- package/.agents/backend/fm-remote-job-lib.sh +1241 -0
- package/.agents/backend/fm-remote-job-reap-orphans.sh +137 -0
- package/.agents/backend/fm-remote-job-worker.sh +1124 -0
- package/.agents/backend/fm-remote-readiness-lib.sh +44 -0
- package/.agents/backend/fm-remote-secondmate-control.sh +340 -0
- package/.agents/backend/fm-review-diff.sh +158 -0
- package/.agents/backend/fm-secondmate-charter-lib.sh +44 -0
- package/.agents/backend/fm-secondmate-nudge-lib.sh +68 -0
- package/.agents/backend/fm-secondmate-parent-lib.sh +70 -0
- package/.agents/backend/fm-secondmate-reconcile.sh +371 -0
- package/.agents/backend/fm-secondmate-registry-lib.sh +311 -0
- package/.agents/backend/fm-secondmate-report.sh +88 -0
- package/.agents/backend/fm-send.sh +1059 -0
- package/.agents/backend/fm-session-lock-lib.sh +176 -0
- package/.agents/backend/fm-session-start.sh +970 -0
- package/.agents/backend/fm-sessionstart-cursor.sh +40 -0
- package/.agents/backend/fm-sessionstart-nudge.sh +45 -0
- package/.agents/backend/fm-sessionstart-run.sh +145 -0
- package/.agents/backend/fm-spawn.sh +3153 -0
- package/.agents/backend/fm-startup-memory-budget-lib.sh +224 -0
- package/.agents/backend/fm-startup-memory-budget.sh +94 -0
- package/.agents/backend/fm-startup-network.sh +642 -0
- package/.agents/backend/fm-stow-cascade.sh +251 -0
- package/.agents/backend/fm-subagent-pretool-check.sh +207 -0
- package/.agents/backend/fm-supervise-daemon.sh +1732 -0
- package/.agents/backend/fm-supervision-instructions.sh +215 -0
- package/.agents/backend/fm-supervision-lib.sh +90 -0
- package/.agents/backend/fm-supervisor-target-lib.sh +78 -0
- package/.agents/backend/fm-tangle-lib.sh +53 -0
- package/.agents/backend/fm-task-inbox-lib.sh +402 -0
- package/.agents/backend/fm-tasks-axi-lib.sh +123 -0
- package/.agents/backend/fm-teardown.sh +2922 -0
- package/.agents/backend/fm-test-isolation-proof.sh +588 -0
- package/.agents/backend/fm-test-run.sh +2191 -0
- package/.agents/backend/fm-timeout-lib.sh +141 -0
- package/.agents/backend/fm-timing-lib.sh +179 -0
- package/.agents/backend/fm-tmux-lib.sh +291 -0
- package/.agents/backend/fm-tool-update-check.sh +898 -0
- package/.agents/backend/fm-trace-context-lib.sh +227 -0
- package/.agents/backend/fm-transition-lib.sh +103 -0
- package/.agents/backend/fm-turnend-guard-cursor.sh +391 -0
- package/.agents/backend/fm-turnend-guard-grok.sh +90 -0
- package/.agents/backend/fm-turnend-guard.sh +432 -0
- package/.agents/backend/fm-update.sh +110 -0
- package/.agents/backend/fm-vendor-auth-probe.sh +190 -0
- package/.agents/backend/fm-voice-client.py +1373 -0
- package/.agents/backend/fm-voice-relay.py +1256 -0
- package/.agents/backend/fm-wake-drain.sh +592 -0
- package/.agents/backend/fm-wake-grant.sh +127 -0
- package/.agents/backend/fm-wake-lib.sh +1849 -0
- package/.agents/backend/fm-watch-arm.sh +602 -0
- package/.agents/backend/fm-watch-checkpoint.sh +109 -0
- package/.agents/backend/fm-watch.sh +1962 -0
- package/.agents/backend/fm-x-dismiss.sh +116 -0
- package/.agents/backend/fm-x-followup.sh +286 -0
- package/.agents/backend/fm-x-lib.sh +1000 -0
- package/.agents/backend/fm-x-link.sh +234 -0
- package/.agents/backend/fm-x-poll.sh +185 -0
- package/.agents/backend/fm-x-reply.sh +385 -0
- package/.agents/backend/fm_voice_frame.py +166 -0
- package/.agents/backend/fm_voice_records.py +574 -0
- package/.agents/backend/model-bridge.py +360 -0
- package/.agents/backend/opencode-go-bridge.py +30 -0
- package/.agents/bus/README.md +12 -0
- package/.agents/bus/messages.json +1 -0
- package/.agents/config/agents.machine.example.yaml +16 -0
- package/.agents/config/agents.yaml.example +72 -0
- package/.agents/config/crew-dispatch.json +22 -0
- package/.agents/config/cron.yaml +11 -0
- package/.agents/config/eindri-dispatch.json +67 -0
- package/.agents/config/eindri-harness +1 -0
- package/.agents/config/startup-memory-budget +1 -0
- package/.agents/filebrowser/.filebrowser.json +6 -0
- package/.agents/filebrowser/README.md +11 -0
- package/.agents/gateway/README.md +12 -0
- package/.agents/github/README.md +15 -0
- package/.agents/github/webhooks/.gitkeep +0 -0
- package/.agents/github/workflows/.gitkeep +0 -0
- package/.agents/harness/opencode/plugins/lib/rodd-operational-input.js +37 -0
- package/.agents/harness/opencode/plugins/package.json +4 -0
- package/.agents/harness/opencode/plugins/saga-sessionstart.js +77 -0
- package/.agents/harness/opencode/plugins/syn-cd-check.js +61 -0
- package/.agents/harness/opencode/plugins/syn-pretool-check.js +68 -0
- package/.agents/harness/opencode/plugins/syn-turnend-guard.js +105 -0
- package/.agents/harness/opencode/plugins/syn-watch-arm.js +521 -0
- package/.agents/memory/README.md +46 -0
- package/.agents/memory/runes_audit.md +5 -0
- package/.agents/migrations/0001-hodd-layout.sh +38 -0
- package/.agents/migrations/0002-a2a-mcp.sh +27 -0
- package/.agents/migrations/0003-private-data-separation.sh +121 -0
- package/.agents/migrations/0004-hoard-and-realms.sh +104 -0
- package/.agents/migrations/0005-roots-out-of-tree.sh +158 -0
- package/.agents/sandbox/Dockerfile.utgard +19 -0
- package/.agents/sandbox/README.md +14 -0
- package/.agents/sandbox/utgard.config.json +14 -0
- package/.agents/skills/README.md +59 -0
- package/.agents/skills/bragi-marketing/README.md +3 -0
- package/.agents/skills/bragi-marketing/SKILL.md +82 -0
- package/.agents/skills/eindri-homes/README.md +3 -0
- package/.agents/skills/eindri-homes/SKILL.md +291 -0
- package/.agents/skills/eindri-homes/assets/control-plane.md +122 -0
- package/.agents/skills/eindri-homes/assets/dispatch.md +80 -0
- package/.agents/skills/frigg-consent/README.md +3 -0
- package/.agents/skills/frigg-consent/SKILL.md +56 -0
- package/.agents/skills/galdr-ymirsystem/README.md +3 -0
- package/.agents/skills/galdr-ymirsystem/SKILL.md +159 -0
- package/.agents/skills/galdr-ymirsystem/assets/README.md +74 -0
- package/.agents/skills/galdr-ymirsystem/assets/brokk-distro-runtime.md +390 -0
- package/.agents/skills/galdr-ymirsystem/assets/build-method.md +113 -0
- package/.agents/skills/galdr-ymirsystem/assets/build-tool-categories.md +178 -0
- package/.agents/skills/galdr-ymirsystem/assets/eindri-orchestration.md +518 -0
- package/.agents/skills/galdr-ymirsystem/assets/eindri-profiles.md +136 -0
- package/.agents/skills/galdr-ymirsystem/assets/harness-integration/README.md +736 -0
- package/.agents/skills/galdr-ymirsystem/assets/harness-integration/claude-code.md +197 -0
- package/.agents/skills/galdr-ymirsystem/assets/harness-integration/codex.md +191 -0
- package/.agents/skills/galdr-ymirsystem/assets/harness-integration/cursor.md +193 -0
- package/.agents/skills/galdr-ymirsystem/assets/harness-integration/opencode.md +262 -0
- package/.agents/skills/galdr-ymirsystem/assets/harness-integration/pi.md +295 -0
- package/.agents/skills/galdr-ymirsystem/assets/hlidskjalf-ui.md +539 -0
- package/.agents/skills/galdr-ymirsystem/assets/installation.md +763 -0
- package/.agents/skills/galdr-ymirsystem/assets/local-models/HOST-DATA.example.md +72 -0
- package/.agents/skills/galdr-ymirsystem/assets/local-models.md +274 -0
- package/.agents/skills/galdr-ymirsystem/assets/memory-well.md +163 -0
- package/.agents/skills/galdr-ymirsystem/assets/nornir-jobs.md +415 -0
- package/.agents/skills/galdr-ymirsystem/assets/norse-naming.md +325 -0
- package/.agents/skills/galdr-ymirsystem/assets/odrerir-hall.md +133 -0
- package/.agents/skills/galdr-ymirsystem/assets/pi-boot/einherjar-spawn.schema.json +81 -0
- package/.agents/skills/galdr-ymirsystem/assets/pi-boot/herdr-profile.toml +75 -0
- package/.agents/skills/galdr-ymirsystem/assets/pi-boot/pi-profile.yml +101 -0
- package/.agents/skills/galdr-ymirsystem/assets/pi-boot/supervision-tree.yml +163 -0
- package/.agents/skills/galdr-ymirsystem/assets/pi-boot-guide.md +58 -0
- package/.agents/skills/galdr-ymirsystem/assets/porting-upstream-to-norse.md +301 -0
- package/.agents/skills/galdr-ymirsystem/assets/principles.md +385 -0
- package/.agents/skills/galdr-ymirsystem/assets/reference-adoption.md +99 -0
- package/.agents/skills/galdr-ymirsystem/assets/registry.md +379 -0
- package/.agents/skills/galdr-ymirsystem/assets/runtime-compliance.md +463 -0
- package/.agents/skills/galdr-ymirsystem/assets/runtime-components.md +553 -0
- package/.agents/skills/galdr-ymirsystem/assets/smidja.md +180 -0
- package/.agents/skills/galdr-ymirsystem/schemas/toon-schemas.md +190 -0
- package/.agents/skills/galdr-ymirsystem/scripts/README.md +45 -0
- package/.agents/skills/galdr-ymirsystem/scripts/bench-one.sh +248 -0
- package/.agents/skills/galdr-ymirsystem/scripts/compliance-check.sh +503 -0
- package/.agents/skills/galdr-ymirsystem/scripts/gpu-sample.sh +43 -0
- package/.agents/skills/galdr-ymirsystem/scripts/stop-all.sh +34 -0
- package/.agents/skills/galdr-ymirsystem/scripts/toon-check.py +188 -0
- package/.agents/skills/gjallarhorn-relay/README.md +3 -0
- package/.agents/skills/gjallarhorn-relay/SKILL.md +283 -0
- package/.agents/skills/groa-update/SKILL.md +90 -0
- package/.agents/skills/hamr-adapters/README.md +3 -0
- package/.agents/skills/hamr-adapters/SKILL.md +123 -0
- package/.agents/skills/hamr-adapters/references/common/control-and-recovery.md +37 -0
- package/.agents/skills/hamr-adapters/references/common/dispatch.md +32 -0
- package/.agents/skills/hamr-adapters/references/common/model-and-effort.md +42 -0
- package/.agents/skills/hamr-adapters/references/common/primary-hooks.md +40 -0
- package/.agents/skills/hamr-adapters/references/harness/claude.md +55 -0
- package/.agents/skills/hamr-adapters/references/harness/codex.md +43 -0
- package/.agents/skills/hamr-adapters/references/harness/cursor.md +75 -0
- package/.agents/skills/hamr-adapters/references/harness/grok.md +69 -0
- package/.agents/skills/hamr-adapters/references/harness/kimi.md +51 -0
- package/.agents/skills/hamr-adapters/references/harness/muse.md +70 -0
- package/.agents/skills/hamr-adapters/references/harness/opencode.md +42 -0
- package/.agents/skills/hamr-adapters/references/harness/pi.md +56 -0
- package/.agents/skills/herdr-panes/README.md +3 -0
- package/.agents/skills/herdr-panes/SKILL.md +92 -0
- package/.agents/skills/herdr-panes/assets/herdr-backend.md +346 -0
- package/.agents/skills/herdr-panes/assets/tmux-backend.md +115 -0
- package/.agents/skills/hnoss-design/DESIGN.md +19 -0
- package/.agents/skills/hnoss-design/README.md +3 -0
- package/.agents/skills/hnoss-design/SKILL.md +83 -0
- package/.agents/skills/hvild-afk/README.md +3 -0
- package/.agents/skills/hvild-afk/SKILL.md +241 -0
- package/.agents/skills/jord-projects/README.md +3 -0
- package/.agents/skills/jord-projects/SKILL.md +92 -0
- package/.agents/skills/lifecycle/SKILL.md +56 -0
- package/.agents/skills/lifecycle/smoke_test.sh +57 -0
- package/.agents/skills/lifecycle/start.sh +21 -0
- package/.agents/skills/lifecycle/status.sh +35 -0
- package/.agents/skills/lifecycle/stop.sh +16 -0
- package/.agents/skills/muninn-stow/README.md +3 -0
- package/.agents/skills/muninn-stow/SKILL.md +309 -0
- package/.agents/skills/no-mistakes/SKILL.md +379 -0
- package/.agents/skills/nornir-schedule/README.md +3 -0
- package/.agents/skills/nornir-schedule/SKILL.md +25 -0
- package/.agents/skills/nornir-schedule/assets/events.md +137 -0
- package/.agents/skills/nornir-schedule/assets/quota.md +131 -0
- package/.agents/skills/nsr-compliance/README.md +3 -0
- package/.agents/skills/nsr-compliance/SKILL.md +29 -0
- package/.agents/skills/nsr-compliance/assets/nsr/README.md +40 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/RULES/README.md +15 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/RULES/git-workflow.md +18 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/RULES/security.md +22 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/RULES/tech-stack.md +8 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/SKILL.md +71 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/config/core_four.yaml +16 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/gates/check_danger.sh +102 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/gates/check_wiring.sh +69 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/gates/validate_code.sh +29 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/gates/verify_docs.py +66 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/generate.sh +109 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/harness/envelopes/result_envelope.json +14 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/harness/envelopes/task_envelope.json +20 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/harness/runner.py +303 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/telemetry/logger.py +112 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/README.md +18 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/config/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/gates/README.md +12 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/gates/check_env.sh +23 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/gates/check_paths.sh +20 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/gates/check_platform.sh +23 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/harness/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/harness/envelopes/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/installer/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/installer/install.sh +125 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/telemetry/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/README.md +20 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/features/README.md +36 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/features/SKILL-template.md +14 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/README.md +25 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/SKILL.md +13 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/create_branch.sh +6 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/safe_commit.sh +9 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/sync_upstream.sh +6 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/README.md +27 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/SKILL.md +15 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/smoke_test.sh +12 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/start.sh +19 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/status.sh +12 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/stop.sh +15 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/README.md +18 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/config/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/config/core_four.yaml +13 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/README.md +12 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_danger.sh +102 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_env.sh +23 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_paths.sh +20 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_platform.sh +23 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_wiring.sh +69 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/envelopes/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/envelopes/result_envelope.json +14 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/envelopes/task_envelope.json +20 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/runner.py +303 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/installer/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/installer/install.sh +125 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/telemetry/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/telemetry/logger.py +112 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/BEST_PRACTICES/README.md +14 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/BEST_PRACTICES/api.md +17 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/BEST_PRACTICES/compliance-wiring.md +155 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/BEST_PRACTICES/frontend.md +15 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/README.md +23 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/clients/README.md +16 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/clients/template-README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/deploy.sh +49 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/envs/README.md +12 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/envs/development.env.example +17 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/envs/production.env.example +17 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/envs/staging.env.example +17 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/tenants/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/tenants/template.env.example +8 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/README.md +26 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/agent.md +7 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/developers/dev-1.md +20 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/linux.md +9 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/macos.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/shared.md +19 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/windows.md +14 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/HOSTING/README.md +25 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/HOSTING/_template.md +41 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/HOSTING/hosting-1.md +41 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/README.md +21 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/RUNBOOK/README.md +15 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/RUNBOOK/deployment.md +19 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/RUNBOOK/disaster-recovery.md +15 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/RUNBOOK/ops-tasks.md +14 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/features/README.md +16 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/project-skills.md +146 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/research/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/research/software-compliance-research.md +269 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/working-with-agents.md +260 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/AGENTS.md +38 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/ARCHITECTURE.md +36 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/BEST_PRACTICES.md +27 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/CI_CD.md +23 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/FEATURES.md +15 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/README.md +22 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/RULES.md +37 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/STRUCTURE.md +45 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/TECH_STACK.md +28 -0
- package/.agents/skills/nsr-compliance/assets/nsr/scaffold-spec.md +63 -0
- package/.agents/skills/nsr-compliance/assets/nsr/scripts/scaffold.sh +103 -0
- package/.agents/skills/nsr-compliance/assets/nsr/scripts/validate.sh +52 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/SKILL.md +71 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/config/core_four.yaml +16 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/gates/check_danger.sh +102 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/gates/check_wiring.sh +69 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/gates/validate_code.sh +29 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/gates/verify_docs.py +66 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/generate.sh +109 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/harness/envelopes/result_envelope.json +14 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/harness/envelopes/task_envelope.json +20 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/harness/runner.py +303 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/telemetry/logger.py +112 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/README.md +18 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/config/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/gates/README.md +12 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/gates/check_env.sh +23 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/gates/check_paths.sh +20 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/gates/check_platform.sh +23 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/harness/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/harness/envelopes/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/installer/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/installer/install.sh +125 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/telemetry/README.md +11 -0
- package/.agents/skills/pr-ops/README.md +3 -0
- package/.agents/skills/pr-ops/SKILL.md +109 -0
- package/.agents/skills/ratatoskr-a2a/README.md +3 -0
- package/.agents/skills/ratatoskr-a2a/SKILL.md +148 -0
- package/.agents/skills/rules-check-drift/SKILL.md +81 -0
- package/.agents/skills/saga-bearings/README.md +3 -0
- package/.agents/skills/saga-bearings/SKILL.md +26 -0
- package/.agents/skills/saga-bearings/assets/bearings.md +161 -0
- package/.agents/skills/saga-bearings/assets/board-template.html +731 -0
- package/.agents/skills/saga-bearings/assets/recap.md +56 -0
- package/.agents/skills/syn-recovery/README.md +3 -0
- package/.agents/skills/syn-recovery/SKILL.md +54 -0
- package/.agents/skills/tyr-check/README.md +3 -0
- package/.agents/skills/tyr-check/SKILL.md +218 -0
- package/.agents/skills/urdh-hold/README.md +3 -0
- package/.agents/skills/urdh-hold/SKILL.md +25 -0
- package/.agents/skills/urdh-hold/assets/decisions.md +15 -0
- package/.agents/skills/urdh-hold/assets/hold.md +54 -0
- package/.agents/skills/vor-diagnostics/README.md +3 -0
- package/.agents/skills/vor-diagnostics/SKILL.md +68 -0
- package/.agents/skills/ymir-host/README.md +3 -0
- package/.agents/skills/ymir-host/SKILL.md +35 -0
- package/.agents/skills/ymir-host/assets/desktop.md +36 -0
- package/.agents/skills/ymir-host/assets/install.md +69 -0
- package/.agents/skills/ymir-host/assets/omarchy.md +297 -0
- package/.agents/skills/ymir-host/assets/runbooks.md +15 -0
- package/.agents/skills/ymir-host/assets/thjazi.md +220 -0
- package/.agents/skills/ymir-host/assets/update.md +64 -0
- package/.agents/tests/assets/board-render-harness.mjs +117 -0
- package/.agents/tests/cmux-test-safety.sh +51 -0
- package/.agents/tests/fixtures.sh +291 -0
- package/.agents/tests/fm-afk-inject-e2e.test.sh +428 -0
- package/.agents/tests/fm-afk-inject-herdr-e2e.test.sh +536 -0
- package/.agents/tests/fm-afk-launch.test.sh +961 -0
- package/.agents/tests/fm-afk-pi-herdr-return-e2e.test.sh +297 -0
- package/.agents/tests/fm-afk-return.test.sh +283 -0
- package/.agents/tests/fm-arm-pretool-check.test.sh +482 -0
- package/.agents/tests/fm-ask-user-authority.test.sh +42 -0
- package/.agents/tests/fm-backend-autodetect-smoke.test.sh +176 -0
- package/.agents/tests/fm-backend-cmux-smoke.test.sh +188 -0
- package/.agents/tests/fm-backend-cmux.test.sh +1166 -0
- package/.agents/tests/fm-backend-herdr-eventwait-smoke.test.sh +136 -0
- package/.agents/tests/fm-backend-herdr-eventwait.test.py +106 -0
- package/.agents/tests/fm-backend-herdr-focus-flash-e2e.test.sh +409 -0
- package/.agents/tests/fm-backend-herdr-launcher-workspace-e2e.test.sh +437 -0
- package/.agents/tests/fm-backend-herdr-presentation-e2e.test.sh +1424 -0
- package/.agents/tests/fm-backend-herdr-prune-safety-e2e.test.sh +180 -0
- package/.agents/tests/fm-backend-herdr-respawn-idem-e2e.test.sh +182 -0
- package/.agents/tests/fm-backend-herdr-smoke.test.sh +355 -0
- package/.agents/tests/fm-backend-herdr-workspace-per-home-e2e.test.sh +251 -0
- package/.agents/tests/fm-backend-herdr.test.sh +4606 -0
- package/.agents/tests/fm-backend-orca.test.sh +1357 -0
- package/.agents/tests/fm-backend-tmux-smoke.test.sh +173 -0
- package/.agents/tests/fm-backend-zellij-smoke.test.sh +205 -0
- package/.agents/tests/fm-backend-zellij.test.sh +1360 -0
- package/.agents/tests/fm-backend.test.sh +1142 -0
- package/.agents/tests/fm-backlog-atomicity.test.sh +2302 -0
- package/.agents/tests/fm-backlog-handoff.test.sh +1360 -0
- package/.agents/tests/fm-bearings-board-render.test.sh +135 -0
- package/.agents/tests/fm-bearings-board.test.sh +414 -0
- package/.agents/tests/fm-bearings-snapshot.test.sh +1990 -0
- package/.agents/tests/fm-bootstrap-network-parallel.test.sh +316 -0
- package/.agents/tests/fm-bootstrap.test.sh +1178 -0
- package/.agents/tests/fm-branch-supervision.test.sh +552 -0
- package/.agents/tests/fm-brief.test.sh +785 -0
- package/.agents/tests/fm-busy-adapter-wiring.test.sh +324 -0
- package/.agents/tests/fm-busy-state.test.sh +465 -0
- package/.agents/tests/fm-calm-pi-extension.test.sh +3979 -0
- package/.agents/tests/fm-captain-hold-lifecycle.test.sh +1187 -0
- package/.agents/tests/fm-cd-pretool-check.test.sh +400 -0
- package/.agents/tests/fm-check-unregister.test.sh +198 -0
- package/.agents/tests/fm-classify-corr-token.test.sh +543 -0
- package/.agents/tests/fm-classify-decision-key.test.sh +340 -0
- package/.agents/tests/fm-claude-stop-autoarm-live-e2e.test.sh +164 -0
- package/.agents/tests/fm-claude-stop-autoarm.test.sh +1190 -0
- package/.agents/tests/fm-cmux-claude-composer-live-e2e.test.sh +110 -0
- package/.agents/tests/fm-codex-continuity-live-e2e.test.sh +55 -0
- package/.agents/tests/fm-composer-ghost.test.sh +716 -0
- package/.agents/tests/fm-composer-lib.test.sh +666 -0
- package/.agents/tests/fm-composer-matrix-live-e2e.test.sh +220 -0
- package/.agents/tests/fm-control-herdr-smoke.test.sh +149 -0
- package/.agents/tests/fm-control-relaunch.test.sh +1530 -0
- package/.agents/tests/fm-control.test.sh +910 -0
- package/.agents/tests/fm-crew-state.test.sh +1610 -0
- package/.agents/tests/fm-cursor-harness.test.sh +404 -0
- package/.agents/tests/fm-cursor-primary-live-e2e.test.sh +217 -0
- package/.agents/tests/fm-cursor-primary.test.sh +708 -0
- package/.agents/tests/fm-daemon.test.sh +2740 -0
- package/.agents/tests/fm-documentation-audiences.test.sh +141 -0
- package/.agents/tests/fm-ensure-agents-md.test.sh +371 -0
- package/.agents/tests/fm-extension-binding.test.sh +2187 -0
- package/.agents/tests/fm-fleet-snapshot-view.test.sh +816 -0
- package/.agents/tests/fm-fleet-sync.test.sh +721 -0
- package/.agents/tests/fm-gate-refuse.test.sh +356 -0
- package/.agents/tests/fm-gitignore-config.test.sh +89 -0
- package/.agents/tests/fm-gotmp.test.sh +230 -0
- package/.agents/tests/fm-grok-continuity-live-e2e.test.sh +112 -0
- package/.agents/tests/fm-grok-harness.test.sh +117 -0
- package/.agents/tests/fm-grok-stop-live-e2e.test.sh +219 -0
- package/.agents/tests/fm-guard-stale-banner.test.sh +709 -0
- package/.agents/tests/fm-harness-adapter-instructions-live-e2e.test.sh +134 -0
- package/.agents/tests/fm-harness-adapter-references.test.sh +30 -0
- package/.agents/tests/fm-harness-liveness-drift-live-e2e.test.sh +151 -0
- package/.agents/tests/fm-herdr-lab.test.sh +243 -0
- package/.agents/tests/fm-herdr-session-cleanup-e2e.test.sh +146 -0
- package/.agents/tests/fm-herdr-session-cleanup.test.sh +329 -0
- package/.agents/tests/fm-herdr-submit-confirm-live-e2e.test.sh +125 -0
- package/.agents/tests/fm-herdr-version-floor-live-e2e.test.sh +144 -0
- package/.agents/tests/fm-home-summary-refresh.test.sh +971 -0
- package/.agents/tests/fm-inactive-reconcile.test.sh +485 -0
- package/.agents/tests/fm-kimi-harness.test.sh +687 -0
- package/.agents/tests/fm-lint-workflows.test.sh +532 -0
- package/.agents/tests/fm-lint.test.sh +1023 -0
- package/.agents/tests/fm-muse-harness.test.sh +932 -0
- package/.agents/tests/fm-muse-signals-live-e2e.test.sh +205 -0
- package/.agents/tests/fm-no-mistakes-required.test.sh +72 -0
- package/.agents/tests/fm-on.test.sh +507 -0
- package/.agents/tests/fm-opencode-primary-live-e2e.test.sh +357 -0
- package/.agents/tests/fm-operational-input.test.sh +160 -0
- package/.agents/tests/fm-peek-remote.test.sh +110 -0
- package/.agents/tests/fm-pending-reply.test.sh +1288 -0
- package/.agents/tests/fm-pi-branch-extension.test.sh +3182 -0
- package/.agents/tests/fm-pi-branch-live-e2e.test.sh +527 -0
- package/.agents/tests/fm-pi-primary-live-e2e.test.sh +345 -0
- package/.agents/tests/fm-pi-primary-types.test.sh +68 -0
- package/.agents/tests/fm-pi-watch-extension.test.sh +2843 -0
- package/.agents/tests/fm-pr-check-security.test.sh +2140 -0
- package/.agents/tests/fm-pr-merge.test.sh +2135 -0
- package/.agents/tests/fm-procevent-quota.test.sh +225 -0
- package/.agents/tests/fm-procevent-when.test.sh +406 -0
- package/.agents/tests/fm-procevent.test.sh +1745 -0
- package/.agents/tests/fm-project-origin.test.sh +110 -0
- package/.agents/tests/fm-public-followup.test.sh +2272 -0
- package/.agents/tests/fm-quota-array-dispatch-live-e2e.test.sh +526 -0
- package/.agents/tests/fm-quota-choose.test.sh +626 -0
- package/.agents/tests/fm-remote-backlog-handoff.test.sh +453 -0
- package/.agents/tests/fm-remote-doctor.test.sh +625 -0
- package/.agents/tests/fm-remote-entrypoint.test.sh +59 -0
- package/.agents/tests/fm-remote-job-orphan-reap.test.sh +205 -0
- package/.agents/tests/fm-remote-job.test.sh +768 -0
- package/.agents/tests/fm-remote-reply.test.sh +520 -0
- package/.agents/tests/fm-remote-secondmate-lifecycle-e2e.test.sh +1256 -0
- package/.agents/tests/fm-remote-secondmate-parent-binding.test.sh +326 -0
- package/.agents/tests/fm-remote-secondmate-trace-context.test.sh +310 -0
- package/.agents/tests/fm-remote-transport-lanes.test.sh +431 -0
- package/.agents/tests/fm-review-diff.test.sh +176 -0
- package/.agents/tests/fm-secondmate-harness.test.sh +2600 -0
- package/.agents/tests/fm-secondmate-lifecycle-e2e.test.sh +259 -0
- package/.agents/tests/fm-secondmate-liveness.test.sh +559 -0
- package/.agents/tests/fm-secondmate-reconcile.test.sh +732 -0
- package/.agents/tests/fm-secondmate-safety.test.sh +2972 -0
- package/.agents/tests/fm-secondmate-sync.test.sh +913 -0
- package/.agents/tests/fm-send-inbox-doorbell-live-e2e.test.sh +206 -0
- package/.agents/tests/fm-send-inbox.test.sh +352 -0
- package/.agents/tests/fm-send-popup-settle.test.sh +167 -0
- package/.agents/tests/fm-send-remote-delivery.test.sh +796 -0
- package/.agents/tests/fm-send-resolve-key.test.sh +551 -0
- package/.agents/tests/fm-send-secondmate-marker-herdr-e2e.test.sh +187 -0
- package/.agents/tests/fm-send-secondmate-marker.test.sh +278 -0
- package/.agents/tests/fm-send-settle.test.sh +147 -0
- package/.agents/tests/fm-send-strict.test.sh +241 -0
- package/.agents/tests/fm-session-lock-ancestry.test.sh +365 -0
- package/.agents/tests/fm-session-start.test.sh +2515 -0
- package/.agents/tests/fm-sessionstart-hook-live-e2e.test.sh +631 -0
- package/.agents/tests/fm-sessionstart-instruction-refresh-live-e2e.test.sh +230 -0
- package/.agents/tests/fm-sessionstart-nudge.test.sh +1039 -0
- package/.agents/tests/fm-shared-captain-inheritance.test.sh +404 -0
- package/.agents/tests/fm-spawn-batch.test.sh +148 -0
- package/.agents/tests/fm-spawn-dispatch-profile.test.sh +827 -0
- package/.agents/tests/fm-spawn-pool-base-freshen.test.sh +440 -0
- package/.agents/tests/fm-spawn-worktree-settle.test.sh +147 -0
- package/.agents/tests/fm-startup-memory-budget.test.sh +333 -0
- package/.agents/tests/fm-startup-network.test.sh +712 -0
- package/.agents/tests/fm-stow-cascade.test.sh +370 -0
- package/.agents/tests/fm-subagent-pretool-check.test.sh +291 -0
- package/.agents/tests/fm-supervision-events.test.sh +156 -0
- package/.agents/tests/fm-supervision-instructions.test.sh +189 -0
- package/.agents/tests/fm-tangle-guard.test.sh +277 -0
- package/.agents/tests/fm-task-delivery.test.sh +420 -0
- package/.agents/tests/fm-task-inbox.test.sh +513 -0
- package/.agents/tests/fm-teardown-endpoint-safety.test.sh +374 -0
- package/.agents/tests/fm-teardown.test.sh +2665 -0
- package/.agents/tests/fm-test-fixture-cleanup.test.sh +172 -0
- package/.agents/tests/fm-test-fixtures.test.sh +132 -0
- package/.agents/tests/fm-test-isolation-proof.test.sh +278 -0
- package/.agents/tests/fm-test-run.test.sh +1196 -0
- package/.agents/tests/fm-tmux-agent-liveness.test.sh +354 -0
- package/.agents/tests/fm-tmux-submit-busy.test.sh +340 -0
- package/.agents/tests/fm-tool-update-check.test.sh +1044 -0
- package/.agents/tests/fm-trace-context-lib.test.sh +253 -0
- package/.agents/tests/fm-trace-context-spawn.test.sh +581 -0
- package/.agents/tests/fm-transition-lib.test.sh +54 -0
- package/.agents/tests/fm-turnend-guard.test.sh +1822 -0
- package/.agents/tests/fm-update.test.sh +304 -0
- package/.agents/tests/fm-vendor-auth-probe.test.sh +395 -0
- package/.agents/tests/fm-voice-relay.test.sh +4741 -0
- package/.agents/tests/fm-wake-daemon-lifecycle-e2e.test.sh +171 -0
- package/.agents/tests/fm-wake-drain-open-decisions-cursor.test.sh +356 -0
- package/.agents/tests/fm-wake-drain-open-decisions.test.sh +226 -0
- package/.agents/tests/fm-wake-drain-unread-status.test.sh +379 -0
- package/.agents/tests/fm-wake-queue.test.sh +1224 -0
- package/.agents/tests/fm-watch-arm.test.sh +821 -0
- package/.agents/tests/fm-watch-checkpoint.test.sh +87 -0
- package/.agents/tests/fm-watch-recovery-loop.test.sh +223 -0
- package/.agents/tests/fm-watch-triage.test.sh +3889 -0
- package/.agents/tests/fm-watcher-lock.test.sh +1133 -0
- package/.agents/tests/fm-x-mode.test.sh +3042 -0
- package/.agents/tests/gleipnir-guard-pretool-check.test.sh +51 -0
- package/.agents/tests/gleipnir-machine-lock.test.sh +130 -0
- package/.agents/tests/herdr-test-safety.sh +42 -0
- package/.agents/tests/lib.sh +315 -0
- package/.agents/tests/remote-herdr-fixture.sh +125 -0
- package/.agents/tests/secondmate-helpers.sh +193 -0
- package/.agents/tests/smoke.test.sh +93 -0
- package/.agents/tests/wake-helpers.sh +338 -0
- package/.agents/tests/zellij-test-safety.sh +60 -0
- package/.agents/tools/README.md +10 -0
- package/.agents/tools/bin/tasks-cli +267 -0
- package/.agents/tools/tasks-cli.ts +216 -0
- package/AGENTS.md +498 -0
- package/CHANGELOG.md +1913 -0
- package/LICENSE +1 -1
- package/NOTICE +63 -0
- package/README.md +114 -60
- package/RULES/01-domains.md +51 -0
- package/RULES/02-agents.md +78 -0
- package/RULES/03-houses.md +61 -0
- package/RULES/04-hoard.md +97 -0
- package/RULES/05-platforms.md +67 -0
- package/RULES/06-append-only.md +108 -0
- package/RULES/07-config.md +101 -0
- package/RULES/08-delivery-gate.md +75 -0
- package/RULES/09-electron.md +58 -0
- package/RULES/README.md +22 -0
- package/bin/README.md +107 -0
- package/bin/a2a-mcp.sh +133 -0
- package/bin/a2a-serve.py +103 -0
- package/bin/a2a-serve.sh +8 -0
- package/bin/a2a-talk.sh +50 -0
- package/bin/a2abridge-ensure.sh +108 -0
- package/bin/agent-run.sh +43 -0
- package/bin/agents-config.sh +256 -0
- package/bin/apodex-smoke-test.sh +105 -0
- package/bin/bifrost-bridge.sh +131 -0
- package/bin/bifrost-ingress.sh +77 -0
- package/bin/bootstrap-macos.sh +112 -0
- package/bin/bootstrap-windows.ps1 +112 -0
- package/bin/branch-guard.sh +64 -0
- package/bin/brokk +73 -0
- package/bin/brokk-classify-lib.sh +1770 -0
- package/bin/brokk-lease-lib.sh +222 -0
- package/bin/brokk-lease.sh +193 -0
- package/bin/brokk-lint.sh +65 -0
- package/bin/brokk-send.sh +51 -0
- package/bin/brokk-update.sh +9 -0
- package/bin/brokk-wake-grant.sh +127 -0
- package/bin/brokk-wake-lib.sh +1849 -0
- package/bin/changelog-assemble.sh +154 -0
- package/bin/changelog-guard.sh +197 -0
- package/bin/crash-sense.sh +173 -0
- package/bin/design-check.sh +80 -0
- package/bin/design-icon.sh +153 -0
- package/bin/desktop-place.sh +224 -0
- package/bin/docs-guard.sh +39 -0
- package/bin/editor-place.sh +225 -0
- package/bin/eindri-acclaim.sh +47 -0
- package/bin/eindri-control.sh +28 -0
- package/bin/eindri-role.sh +83 -0
- package/bin/eindri-seat.sh +83 -0
- package/bin/eindri-seen.sh +54 -0
- package/bin/eindri-send.sh +15 -0
- package/bin/eindri-start.sh +98 -0
- package/bin/eindri-watch.sh +57 -0
- package/bin/einherjar-spawn.sh +576 -0
- package/bin/eir-doctor.sh +158 -0
- package/bin/erindi-brief.sh +271 -0
- package/bin/feature-inventory.sh +73 -0
- package/bin/fleet-apply.sh +81 -0
- package/bin/github-deploy.sh +94 -0
- package/bin/gjallarhorn-expose.sh +136 -0
- package/bin/gjallarhorn-notify.sh +71 -0
- package/bin/gjallarhorn-purge.sh +67 -0
- package/bin/gjallarhorn-tunnel.sh +85 -0
- package/bin/gleipnir-lock-lib.sh +284 -0
- package/bin/groa-update.sh +130 -0
- package/bin/hall-snapshot.sh +111 -0
- package/bin/hamr-harness.sh +246 -0
- package/bin/heimdall-ssh-keys.sh +374 -0
- package/bin/herdr-agents.py +44 -0
- package/bin/herdr-ensure.sh +104 -0
- package/bin/herdr-run.sh +452 -0
- package/bin/hermes-ensure.sh +88 -0
- package/bin/hlidskjalf-agents.sh +172 -0
- package/bin/hlidskjalf-usage.sh +196 -0
- package/bin/hoard-guard.sh +135 -0
- package/bin/hoard-lib.sh +105 -0
- package/bin/hodd.sh +102 -0
- package/bin/host-sense.sh +199 -0
- package/bin/huginn-research-worker.sh +121 -0
- package/bin/local-model-lock.sh +70 -0
- package/bin/mimir-bridge.py +259 -0
- package/bin/mimir-bridge.sh +100 -0
- package/bin/mimir-ingest.sh +131 -0
- package/bin/mimir-reflect.sh +27 -0
- package/bin/mimir.sh +113 -0
- package/bin/mjollnir-webhook.sh +72 -0
- package/bin/mjollnir.sh +104 -0
- package/bin/model-hardware.sh +96 -0
- package/bin/model-resolve.sh +160 -0
- package/bin/models-detect.sh +178 -0
- package/bin/nornir-cron-start.sh +162 -0
- package/bin/nornir-job-daily-briefing.sh +191 -0
- package/bin/nornir-job-git-sync.sh +152 -0
- package/bin/nornir-job-hall-snapshot.sh +28 -0
- package/bin/nornir-job-memory-housekeeping.sh +114 -0
- package/bin/nornir-job-nsr-compliance.sh +54 -0
- package/bin/nornir-job-observer.sh +166 -0
- package/bin/nornir-job-skillopt-sleep.sh +76 -0
- package/bin/npm-publish.sh +136 -0
- package/bin/omarchy-hook-install.sh +60 -0
- package/bin/omarchy-install.sh +161 -0
- package/bin/omarchy-plugins.sh +187 -0
- package/bin/omarchy-sense.sh +162 -0
- package/bin/perm-guard.sh +30 -0
- package/bin/pi-agent.sh +68 -0
- package/bin/pi-ensure.sh +77 -0
- package/bin/pi-local.sh +37 -0
- package/bin/pi-model-agnostic.sh +71 -0
- package/bin/pi-seat.sh +63 -0
- package/bin/prereq-ensure.sh +166 -0
- package/bin/private-guard.sh +58 -0
- package/bin/project-git.sh +69 -0
- package/bin/public-guard.sh +71 -0
- package/bin/ratatoskr.sh +49 -0
- package/bin/realm-lib.sh +32 -0
- package/bin/repo-scrub.sh +62 -0
- package/bin/rodd-operational-input.sh +250 -0
- package/bin/runes-append.sh +198 -0
- package/bin/saga-session-start.sh +172 -0
- package/bin/saga-sessionstart-run.sh +79 -0
- package/bin/saga-wake-drain.sh +41 -0
- package/bin/secret-guard.sh +63 -0
- package/bin/sessrumnir-ensure.sh +100 -0
- package/bin/sessrumnir-sync.sh +237 -0
- package/bin/sessrumnir.sh +104 -0
- package/bin/skillopt-setup.sh +76 -0
- package/bin/skuld-branch-outcome.sh +203 -0
- package/bin/skuld-branch-prompt.sh +101 -0
- package/bin/smidja-bootstrap.sh +94 -0
- package/bin/smidja-observe.sh +86 -0
- package/bin/syn-arm-pretool-check.sh +57 -0
- package/bin/syn-asset-pretool-check.sh +89 -0
- package/bin/syn-cd-pretool-check.sh +28 -0
- package/bin/syn-guard-pretool-check.sh +83 -0
- package/bin/syn-spawn-pretool-check.sh +58 -0
- package/bin/syn-turnend-guard.sh +36 -0
- package/bin/syn-watch-arm.sh +99 -0
- package/bin/tailscale-sync.sh +203 -0
- package/bin/telegram-bot.sh +82 -0
- package/bin/toolchain.sh +74 -0
- package/bin/ui-truth-check.sh +75 -0
- package/bin/utgard.sh +111 -0
- package/bin/valhalla.sh +115 -0
- package/bin/valknut-load.sh +298 -0
- package/bin/vor-crew-state.sh +124 -0
- package/bin/wedge-notify.sh +60 -0
- package/bin/workspace-provision.sh +80 -0
- package/bin/workspace-rag.sh +163 -0
- package/bin/wyrd-db.sh +47 -0
- package/bin/yggdrasil.sh +152 -0
- package/bin/ymir-edit.sh +145 -0
- package/bin/ymir-install.sh +806 -0
- package/bin/ymir-invite.sh +93 -0
- package/bin/ymir-isolation.sh +88 -0
- package/bin/ymir-migrate.sh +61 -0
- package/bin/ymir-plan.sh +356 -0
- package/bin/ymir-platform.sh +348 -0
- package/bin/ymir-say.sh +110 -0
- package/bin/ymir-setup-auth.sh +119 -0
- package/bin/ymir-validate.sh +193 -0
- package/bin/ymir.js +74 -16
- package/docs/Architecture.md +339 -0
- package/docs/design.md +351 -0
- package/docs/installations/README.md +63 -0
- package/docs/installations/ymir-home.md +93 -0
- package/docs/integration.md +105 -0
- package/docs/lore.md +1060 -0
- package/docs/research/agent-harnesses.md +290 -0
- package/docs/runbooks/README.md +19 -0
- package/docs/runbooks/a2a.md +91 -0
- package/docs/runbooks/agent-permissions.md +99 -0
- package/docs/runbooks/agents.md +57 -0
- package/docs/runbooks/models.md +69 -0
- package/docs/runbooks/realm-onboarding.md +60 -0
- package/docs/runbooks/secrets-and-hoard.md +60 -0
- package/docs/runbooks/updates-and-migrations.md +110 -0
- package/docs/runbooks/worktrees-isolation.md +72 -0
- package/docs/session-start.md +105 -0
- package/docs/skillopt-integration.md +321 -0
- package/docs/sync-system.md +66 -0
- package/docs/workspaces.md +104 -0
- package/docs/ymir-rut.md +260 -0
- package/package.json +54 -14
- package/packaging/build.sh +74 -0
- package/packaging/macos/Ymir Installer.command +43 -0
- package/packaging/windows/ymir-setup.nsi +74 -0
- package/scripts/README.md +22 -0
- package/scripts/electron.sh +269 -0
- package/scripts/lower.sh +34 -0
- package/scripts/raise.sh +42 -0
- package/scripts/start.sh +217 -0
- package/scripts/stop.sh +113 -0
- package/install.sh +0 -35
|
@@ -0,0 +1,878 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# fm-control.sh - the CONTROL PLANE for a firstmate-owned agent: allowlisted
|
|
3
|
+
# lifecycle verbs addressed to an exact task id.
|
|
4
|
+
#
|
|
5
|
+
# Usage: fm-control.sh <task-id> interrupt
|
|
6
|
+
# fm-control.sh <task-id> exit
|
|
7
|
+
# fm-control.sh <task-id> relaunch [--harness <name>] [--model <name>]
|
|
8
|
+
# [--effort <level>]
|
|
9
|
+
# (--note <text> | --note-file <path>)
|
|
10
|
+
#
|
|
11
|
+
# Why this exists, and how it differs from fm-send.sh. bin/fm-send.sh is the
|
|
12
|
+
# DATA plane: conversational text for the agent to read, always routing-marked
|
|
13
|
+
# for a kind=secondmate target so the reply returns through the status path.
|
|
14
|
+
# That marking is right for a message and wrong for a lifecycle command - a
|
|
15
|
+
# marked "/quit" arrives as ordinary chat the agent reasons ABOUT instead of
|
|
16
|
+
# executing. This script is the control plane: semantic process control with a
|
|
17
|
+
# closed verb list, per-harness mechanics owned by an executable adapter
|
|
18
|
+
# (bin/fm-control-lib.sh) rather than improvised in agent prose, and a verified
|
|
19
|
+
# postcondition for every action. There is deliberately NO arbitrary-text and
|
|
20
|
+
# NO generic raw-key entry point here; fm-send remains the only way to send an
|
|
21
|
+
# agent something to read.
|
|
22
|
+
#
|
|
23
|
+
# interrupt Deliver the harness's verified interrupt sequence. The agent
|
|
24
|
+
# keeps running. Postcondition: delivery succeeded, the endpoint
|
|
25
|
+
# still exists, and the agent is still alive where the backend can
|
|
26
|
+
# classify that. Cancellation is confirmed only from an adapter-
|
|
27
|
+
# owned acknowledgement and otherwise reported unconfirmed. Busy
|
|
28
|
+
# state is never rewritten as proof of the action.
|
|
29
|
+
# exit Stop the agent, preserving its terminal endpoint, worktree, and
|
|
30
|
+
# every uncommitted change. Interrupts first when the task reads
|
|
31
|
+
# busy, then submits the harness's exit command. Postcondition:
|
|
32
|
+
# the backend's recovery-grade classifier reports the agent gone.
|
|
33
|
+
# Already-stopped is success (idempotent).
|
|
34
|
+
# relaunch Transactionally replace the running agent with a new one, in the
|
|
35
|
+
# SAME endpoint and SAME worktree, on the same or a newly chosen
|
|
36
|
+
# harness/model/effort - so switching harness is one ordinary use
|
|
37
|
+
# of this verb. With no explicit axis, a secondmate re-resolves its
|
|
38
|
+
# durable config/secondmate-harness pin (harness plus its optional
|
|
39
|
+
# model and effort tokens) exactly as any other respawn does, while
|
|
40
|
+
# a ship or scout keeps the exact adapter already recorded for it.
|
|
41
|
+
# A prefixed raw-command basename cannot reconstruct its launch
|
|
42
|
+
# command, so relaunch requires an explicit --harness for it.
|
|
43
|
+
# --note is required for a ship or scout, whose replacement
|
|
44
|
+
# inherits the local copy but none of the conversation; a
|
|
45
|
+
# secondmate reconciles its own home's records at startup, so its
|
|
46
|
+
# standing charter is never rewritten.
|
|
47
|
+
# Records a durable checkpoint and that note, exits the old agent,
|
|
48
|
+
# then delegates the launch to its single owner,
|
|
49
|
+
# bin/fm-spawn.sh --relaunch. A failure before publication keeps
|
|
50
|
+
# the prior durable record in place and reports the concrete
|
|
51
|
+
# state; it never leaves a half-transitioned task claiming to be
|
|
52
|
+
# running.
|
|
53
|
+
#
|
|
54
|
+
# Teardown and discard are NOT verbs here and never will be. `exit` stops an
|
|
55
|
+
# agent and preserves everything else; removing a worktree, killing an
|
|
56
|
+
# endpoint, or discarding work stays with bin/fm-teardown.sh, which owns the
|
|
57
|
+
# landed-work test.
|
|
58
|
+
#
|
|
59
|
+
# `resume` is not a verb: it is not deterministic across the verified adapters
|
|
60
|
+
# (bin/fm-control-lib.sh's header owns that reasoning). `relaunch` covers the
|
|
61
|
+
# same need for every adapter because the brief on disk, not a harness-private
|
|
62
|
+
# session, is the durable instruction.
|
|
63
|
+
#
|
|
64
|
+
# Targeting is EXACT: only a bare task id with a state/<id>.meta record in
|
|
65
|
+
# THIS home is accepted, and the record must pass the shared endpoint-identity
|
|
66
|
+
# validation (bin/fm-backend.sh's fm_backend_validate_task_endpoint). A legacy
|
|
67
|
+
# fm-<id> label, an explicit session:window endpoint, and a bare window name
|
|
68
|
+
# are all refused - a lifecycle command delivered to the wrong endpoint is far
|
|
69
|
+
# worse than a loud refusal.
|
|
70
|
+
#
|
|
71
|
+
# A remotely placed secondmate is refused by name: its agent runs on another
|
|
72
|
+
# host, so no postcondition this plane verifies could be read for it here.
|
|
73
|
+
#
|
|
74
|
+
# Fail-closed boundaries:
|
|
75
|
+
# - An unverified harness, or a harness whose control mechanics are unknown,
|
|
76
|
+
# is refused rather than guessed at.
|
|
77
|
+
# - A backend that cannot deliver the harness's interrupt key is refused
|
|
78
|
+
# (Orca's terminal API has no Escape).
|
|
79
|
+
# - `exit` and `relaunch` require a backend with a recovery-grade agent-state
|
|
80
|
+
# classifier (tmux, herdr), because without one the "the agent stopped"
|
|
81
|
+
# postcondition cannot be proven. zellij, orca, and cmux are refused rather
|
|
82
|
+
# than reported as successful blind.
|
|
83
|
+
# - An ambiguous or unreadable endpoint state refuses; only a positively
|
|
84
|
+
# classified state acts.
|
|
85
|
+
#
|
|
86
|
+
# Environment knobs (all bounded waits, seconds):
|
|
87
|
+
# FM_CONTROL_POLL poll interval for postcondition waits (0.5)
|
|
88
|
+
# FM_CONTROL_SETTLE_WAIT adapter acknowledgement wait after interrupt (5)
|
|
89
|
+
# FM_CONTROL_EXIT_WAIT alive->dead wait after the exit command (30)
|
|
90
|
+
# FM_CONTROL_LAUNCH_WAIT dead->alive wait after a relaunch (90)
|
|
91
|
+
# FM_CONTROL_EXIT_RETRIES Enter retries for the exit command (3)
|
|
92
|
+
set -eu
|
|
93
|
+
|
|
94
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
95
|
+
FM_ROOT="${FM_ROOT_OVERRIDE:-$(cd "$SCRIPT_DIR/.." && pwd)}"
|
|
96
|
+
|
|
97
|
+
usage() {
|
|
98
|
+
# The whole leading comment block, ending at the first non-comment line.
|
|
99
|
+
sed -n '2,${/^#/!q;p;}' "$0" | sed 's/^# \{0,1\}//'
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
case "${1:-}" in
|
|
103
|
+
-h|--help) usage; exit 0 ;;
|
|
104
|
+
esac
|
|
105
|
+
|
|
106
|
+
# shellcheck source=bin/fm-gate-refuse-lib.sh
|
|
107
|
+
. "$SCRIPT_DIR/fm-gate-refuse-lib.sh"
|
|
108
|
+
# Fail closed before any fleet mutation: a no-mistakes gate agent must never
|
|
109
|
+
# drive a crewmate's lifecycle (see bin/fm-gate-refuse-lib.sh).
|
|
110
|
+
fm_refuse_if_gate_agent
|
|
111
|
+
|
|
112
|
+
if [ -z "${FM_HOME+x}" ] || [ -z "${FM_HOME:-}" ]; then
|
|
113
|
+
echo "error: FM_HOME is not set; fm-control refuses to resolve a task without an explicit firstmate home" >&2
|
|
114
|
+
exit 1
|
|
115
|
+
fi
|
|
116
|
+
[ -d "$FM_HOME" ] || {
|
|
117
|
+
echo "error: FM_HOME '$FM_HOME' is not a directory" >&2
|
|
118
|
+
exit 1
|
|
119
|
+
}
|
|
120
|
+
STATE="${FM_STATE_OVERRIDE:-$FM_HOME/state}"
|
|
121
|
+
DATA="${FM_DATA_OVERRIDE:-$FM_HOME/data}"
|
|
122
|
+
[ -d "$STATE" ] || {
|
|
123
|
+
echo "error: state dir '$STATE' is missing; fm-control cannot resolve tasks for FM_HOME '$FM_HOME'" >&2
|
|
124
|
+
exit 1
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
# shellcheck source=bin/fm-backend.sh
|
|
128
|
+
. "$SCRIPT_DIR/fm-backend.sh"
|
|
129
|
+
# shellcheck source=bin/fm-busy-lib.sh
|
|
130
|
+
. "$SCRIPT_DIR/fm-busy-lib.sh"
|
|
131
|
+
# shellcheck source=bin/fm-control-lib.sh
|
|
132
|
+
. "$SCRIPT_DIR/fm-control-lib.sh"
|
|
133
|
+
# shellcheck source=bin/fm-pr-lib.sh
|
|
134
|
+
. "$SCRIPT_DIR/fm-pr-lib.sh"
|
|
135
|
+
# shellcheck source=bin/fm-wake-lib.sh
|
|
136
|
+
. "$SCRIPT_DIR/fm-wake-lib.sh"
|
|
137
|
+
|
|
138
|
+
POLL=${FM_CONTROL_POLL:-0.5}
|
|
139
|
+
SETTLE_WAIT=${FM_CONTROL_SETTLE_WAIT:-5}
|
|
140
|
+
EXIT_WAIT=${FM_CONTROL_EXIT_WAIT:-30}
|
|
141
|
+
LAUNCH_WAIT=${FM_CONTROL_LAUNCH_WAIT:-90}
|
|
142
|
+
EXIT_RETRIES=${FM_CONTROL_EXIT_RETRIES:-3}
|
|
143
|
+
|
|
144
|
+
die() { # <message>
|
|
145
|
+
echo "error: $1" >&2
|
|
146
|
+
exit 1
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
CONTROL_LOCK=
|
|
150
|
+
CONTROL_LOCK_HELD=0
|
|
151
|
+
RELAUNCH_ACTIVE=0
|
|
152
|
+
RELAUNCH_PHASE=start
|
|
153
|
+
|
|
154
|
+
control_cleanup() {
|
|
155
|
+
local status=$?
|
|
156
|
+
if [ "$RELAUNCH_ACTIVE" = 1 ] \
|
|
157
|
+
&& declare -F relaunch_rollback >/dev/null 2>&1; then
|
|
158
|
+
relaunch_rollback || true
|
|
159
|
+
fi
|
|
160
|
+
if [ "$CONTROL_LOCK_HELD" = 1 ]; then
|
|
161
|
+
CONTROL_LOCK_HELD=0
|
|
162
|
+
fm_lock_release "$CONTROL_LOCK" || true
|
|
163
|
+
fi
|
|
164
|
+
if declare -F fm_lease_guard_release >/dev/null 2>&1; then
|
|
165
|
+
fm_lease_guard_release || true
|
|
166
|
+
fi
|
|
167
|
+
return "$status"
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
# --- argument parsing -------------------------------------------------------
|
|
171
|
+
|
|
172
|
+
RAW_ID=${1:-}
|
|
173
|
+
VERB=${2:-}
|
|
174
|
+
[ -n "$RAW_ID" ] && [ -n "$VERB" ] || { usage >&2; exit 2; }
|
|
175
|
+
shift 2
|
|
176
|
+
|
|
177
|
+
if ! fm_control_verb_allowed "$VERB"; then
|
|
178
|
+
{
|
|
179
|
+
if [ "$VERB" = resume ]; then
|
|
180
|
+
echo "error: 'resume' is not a control verb: resuming an exited agent is not deterministic across the verified adapters (codex and grok need a session id printed at exit, opencode continues the most recent session for the cwd, and claude, pi, pi-signed, and kimi have no verified pane-resume contract). Use 'relaunch', which carries the brief plus a progress note into a fresh agent on any adapter."
|
|
181
|
+
else
|
|
182
|
+
echo "error: '$VERB' is not a control verb"
|
|
183
|
+
fi
|
|
184
|
+
echo "allowed verbs:"
|
|
185
|
+
fm_control_verbs | sed 's/^/ /'
|
|
186
|
+
} >&2
|
|
187
|
+
exit 2
|
|
188
|
+
fi
|
|
189
|
+
|
|
190
|
+
NEW_HARNESS=
|
|
191
|
+
NEW_MODEL=
|
|
192
|
+
NEW_EFFORT=
|
|
193
|
+
HARNESS_SET=0
|
|
194
|
+
MODEL_SET=0
|
|
195
|
+
EFFORT_SET=0
|
|
196
|
+
NOTE=
|
|
197
|
+
NOTE_SET=0
|
|
198
|
+
control_want_value=
|
|
199
|
+
for control_arg in "$@"; do
|
|
200
|
+
if [ -n "$control_want_value" ]; then
|
|
201
|
+
case "$control_arg" in
|
|
202
|
+
--*) die "--$control_want_value requires a value" ;;
|
|
203
|
+
esac
|
|
204
|
+
case "$control_want_value" in
|
|
205
|
+
harness) NEW_HARNESS=$control_arg; HARNESS_SET=1 ;;
|
|
206
|
+
model) NEW_MODEL=$control_arg; MODEL_SET=1 ;;
|
|
207
|
+
effort) NEW_EFFORT=$control_arg; EFFORT_SET=1 ;;
|
|
208
|
+
note) NOTE=$control_arg; NOTE_SET=1 ;;
|
|
209
|
+
note_file)
|
|
210
|
+
[ -f "$control_arg" ] || die "--note-file '$control_arg' is not a readable file"
|
|
211
|
+
NOTE=$(cat "$control_arg")
|
|
212
|
+
NOTE_SET=1
|
|
213
|
+
;;
|
|
214
|
+
esac
|
|
215
|
+
control_want_value=
|
|
216
|
+
continue
|
|
217
|
+
fi
|
|
218
|
+
case "$control_arg" in
|
|
219
|
+
--harness) control_want_value=harness ;;
|
|
220
|
+
--harness=*) NEW_HARNESS=${control_arg#--harness=}; HARNESS_SET=1 ;;
|
|
221
|
+
--model) control_want_value=model ;;
|
|
222
|
+
--model=*) NEW_MODEL=${control_arg#--model=}; MODEL_SET=1 ;;
|
|
223
|
+
--effort) control_want_value=effort ;;
|
|
224
|
+
--effort=*) NEW_EFFORT=${control_arg#--effort=}; EFFORT_SET=1 ;;
|
|
225
|
+
--note) control_want_value=note ;;
|
|
226
|
+
--note=*) NOTE=${control_arg#--note=}; NOTE_SET=1 ;;
|
|
227
|
+
--note-file) control_want_value=note_file ;;
|
|
228
|
+
--note-file=*)
|
|
229
|
+
[ -f "${control_arg#--note-file=}" ] || die "--note-file '${control_arg#--note-file=}' is not a readable file"
|
|
230
|
+
NOTE=$(cat "${control_arg#--note-file=}")
|
|
231
|
+
NOTE_SET=1
|
|
232
|
+
;;
|
|
233
|
+
*) die "unexpected argument '$control_arg'" ;;
|
|
234
|
+
esac
|
|
235
|
+
done
|
|
236
|
+
if [ -n "$control_want_value" ]; then
|
|
237
|
+
[ "$control_want_value" = note_file ] && die "--note-file requires a value"
|
|
238
|
+
die "--$control_want_value requires a value"
|
|
239
|
+
fi
|
|
240
|
+
|
|
241
|
+
if [ "$VERB" != relaunch ]; then
|
|
242
|
+
[ "$HARNESS_SET" = 0 ] && [ "$MODEL_SET" = 0 ] && [ "$EFFORT_SET" = 0 ] && [ "$NOTE_SET" = 0 ] \
|
|
243
|
+
|| die "--harness, --model, --effort, and --note apply to 'relaunch' only"
|
|
244
|
+
fi
|
|
245
|
+
[ "$HARNESS_SET" = 0 ] || [ -n "$NEW_HARNESS" ] || die "--harness requires a non-empty value"
|
|
246
|
+
[ "$MODEL_SET" = 0 ] || [ -n "$NEW_MODEL" ] || die "--model requires a non-empty value"
|
|
247
|
+
[ "$EFFORT_SET" = 0 ] || [ -n "$NEW_EFFORT" ] || die "--effort requires a non-empty value"
|
|
248
|
+
case "$NEW_EFFORT" in
|
|
249
|
+
''|low|medium|high|xhigh|max) ;;
|
|
250
|
+
*) die "--effort must be one of low, medium, high, xhigh, max" ;;
|
|
251
|
+
esac
|
|
252
|
+
|
|
253
|
+
# --- exact task-id resolution ----------------------------------------------
|
|
254
|
+
|
|
255
|
+
case "$RAW_ID" in
|
|
256
|
+
*:*) die "'$RAW_ID' is an explicit backend endpoint; fm-control accepts an exact task id only, so a lifecycle command can never land on an endpoint this home does not own" ;;
|
|
257
|
+
esac
|
|
258
|
+
if ! fm_task_id_creation_valid "$RAW_ID"; then
|
|
259
|
+
die "'$RAW_ID' is not a valid task id"
|
|
260
|
+
fi
|
|
261
|
+
ID=$RAW_ID
|
|
262
|
+
# Supervision lease guard: lifecycle control is overlap territory between the
|
|
263
|
+
# two Pi supervision actors; refuse while the OTHER actor holds this task's
|
|
264
|
+
# live lease (contract: bin/fm-lease-lib.sh; no-op in homes without leases).
|
|
265
|
+
# shellcheck source=bin/fm-lease-lib.sh
|
|
266
|
+
. "$SCRIPT_DIR/fm-lease-lib.sh"
|
|
267
|
+
fm_lease_guard "$ID" "lifecycle control (fm-control)"
|
|
268
|
+
CONTROL_LOCK="$STATE/.control-$ID.lock"
|
|
269
|
+
trap control_cleanup EXIT
|
|
270
|
+
fm_lock_try_acquire "$CONTROL_LOCK" \
|
|
271
|
+
|| die "another lifecycle action is already running for task $ID"
|
|
272
|
+
CONTROL_LOCK_HELD=1
|
|
273
|
+
META="$STATE/$ID.meta"
|
|
274
|
+
if [ ! -f "$META" ]; then
|
|
275
|
+
case "$RAW_ID" in
|
|
276
|
+
fm-*)
|
|
277
|
+
if [ -f "$STATE/${RAW_ID#fm-}.meta" ]; then
|
|
278
|
+
die "'$RAW_ID' is a window label, not a task id; pass the exact task id '${RAW_ID#fm-}'"
|
|
279
|
+
fi
|
|
280
|
+
;;
|
|
281
|
+
esac
|
|
282
|
+
die "no task '$ID' in $STATE (fm-control resolves an exact task id only)"
|
|
283
|
+
fi
|
|
284
|
+
|
|
285
|
+
# A remotely placed secondmate records its endpoint on ANOTHER host, so every
|
|
286
|
+
# postcondition this plane verifies - the agent-state classification, the busy
|
|
287
|
+
# verdict, the endpoint's existence - would be read here for an endpoint that
|
|
288
|
+
# does not live here. Endpoint validation already refuses such a record, since
|
|
289
|
+
# `window=remote:<id>` can never match a local backend's required shape, so
|
|
290
|
+
# nothing can be delivered to a wrong endpoint either way. What that refusal
|
|
291
|
+
# cannot say is WHY, and "malformed metadata" is the wrong thing to tell an
|
|
292
|
+
# operator about a correctly configured remote route. Name the placement
|
|
293
|
+
# instead, using the same `remote_host` signal bin/fm-send.sh routes on.
|
|
294
|
+
if [ -n "$(fm_meta_get "$META" remote_host)" ]; then
|
|
295
|
+
die "task $ID is a remotely placed secondmate on $(fm_meta_get "$META" remote_host); its agent runs outside this home, so no lifecycle action here could verify that it interrupted, stopped, or came back. Drive its lifecycle on that host, and reconcile it through the secondmate recovery path rather than this plane"
|
|
296
|
+
fi
|
|
297
|
+
|
|
298
|
+
fm_backend_validate_task_endpoint "$META" "$ID" || exit 1
|
|
299
|
+
BACKEND=$FM_BACKEND_VALIDATED_BACKEND
|
|
300
|
+
T=$FM_BACKEND_VALIDATED_TARGET
|
|
301
|
+
LABEL="fm-$ID"
|
|
302
|
+
RECORDED_HARNESS=$(fm_meta_get "$META" harness)
|
|
303
|
+
KIND=$(fm_meta_get "$META" kind)
|
|
304
|
+
WT=$(fm_meta_get "$META" worktree)
|
|
305
|
+
[ -n "$KIND" ] || KIND=ship
|
|
306
|
+
|
|
307
|
+
HARNESS=$(fm_control_harness_family "$RECORDED_HARNESS") \
|
|
308
|
+
|| die "task $ID records harness '${RECORDED_HARNESS:-none}', which has no verified control mechanics; fm-control refuses to guess an interrupt key or exit command"
|
|
309
|
+
fm_control_harness_supported "$HARNESS" \
|
|
310
|
+
|| die "task $ID records harness '${RECORDED_HARNESS:-none}', which has no verified control mechanics; fm-control refuses to guess an interrupt key or exit command"
|
|
311
|
+
|
|
312
|
+
fm_backend_validate "$BACKEND" || exit 1
|
|
313
|
+
|
|
314
|
+
# --- shared helpers ---------------------------------------------------------
|
|
315
|
+
|
|
316
|
+
agent_state() {
|
|
317
|
+
fm_backend_agent_state "$BACKEND" "$T"
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
busy_verdict() {
|
|
321
|
+
fm_busy_classify_meta "$META" "$ID" "$STATE"
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
# wait_agent_state <wanted...> <timeout>: poll until agent_state prints one of
|
|
325
|
+
# the wanted values. Prints the final observed state; returns 0 on a match.
|
|
326
|
+
wait_agent_state() { # <timeout> <wanted>...
|
|
327
|
+
local timeout=$1 state want elapsed=0
|
|
328
|
+
shift
|
|
329
|
+
while :; do
|
|
330
|
+
state=$(agent_state)
|
|
331
|
+
for want in "$@"; do
|
|
332
|
+
if [ "$state" = "$want" ]; then
|
|
333
|
+
printf '%s' "$state"
|
|
334
|
+
return 0
|
|
335
|
+
fi
|
|
336
|
+
done
|
|
337
|
+
awk -v e="$elapsed" -v t="$timeout" 'BEGIN{exit !(e < t)}' || break
|
|
338
|
+
sleep "$POLL"
|
|
339
|
+
elapsed=$(awk -v e="$elapsed" -v p="$POLL" 'BEGIN{printf "%.3f", e + p}')
|
|
340
|
+
done
|
|
341
|
+
printf '%s' "$state"
|
|
342
|
+
return 1
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
require_state_verified_backend() { # <verb>
|
|
346
|
+
fm_control_backend_state_verified "$BACKEND" && return 0
|
|
347
|
+
die "task $ID runs on the $BACKEND backend, which has no recovery-grade agent-state classifier, so '$1' cannot prove the agent actually stopped; refusing rather than reporting an unproven transition as done"
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
# send_interrupt_keys: deliver the harness's interrupt key the verified number
|
|
351
|
+
# of times, then the composer-clear key when the adapter needs one. Refuses
|
|
352
|
+
# before sending anything when the backend cannot deliver either key, because
|
|
353
|
+
# an interrupt that cancels the turn but leaves the restored prompt in the
|
|
354
|
+
# composer would make the next submitted line concatenate onto it.
|
|
355
|
+
send_interrupt_keys() {
|
|
356
|
+
local key repeat clear i=0
|
|
357
|
+
key=$(fm_control_interrupt_key "$HARNESS")
|
|
358
|
+
repeat=$(fm_control_interrupt_repeat "$HARNESS")
|
|
359
|
+
clear=$(fm_control_interrupt_clear_key "$HARNESS")
|
|
360
|
+
fm_control_backend_supports_key "$BACKEND" "$key" \
|
|
361
|
+
|| die "harness $HARNESS interrupts with $key, which the $BACKEND backend cannot deliver; refusing to send a different key"
|
|
362
|
+
[ -z "$clear" ] || fm_control_backend_supports_key "$BACKEND" "$clear" \
|
|
363
|
+
|| die "harness $HARNESS needs $clear to clear its composer after an interrupt, which the $BACKEND backend cannot deliver; refusing to leave the cancelled prompt where the next submitted line would concatenate onto it"
|
|
364
|
+
while [ "$i" -lt "$repeat" ]; do
|
|
365
|
+
fm_backend_send_key "$BACKEND" "$T" "$key" "$LABEL" \
|
|
366
|
+
|| die "interrupt key $key was not delivered to task $ID on $BACKEND"
|
|
367
|
+
i=$((i + 1))
|
|
368
|
+
[ "$i" -ge "$repeat" ] || sleep 0.2
|
|
369
|
+
done
|
|
370
|
+
[ -z "$clear" ] || fm_backend_send_key "$BACKEND" "$T" "$clear" "$LABEL" \
|
|
371
|
+
|| die "interrupt key $key reached task $ID, but $clear did not, so its composer still holds the cancelled prompt; clear it before the next lifecycle action"
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
prepare_interrupt_ack() {
|
|
375
|
+
INTERRUPT_ACK_SOURCE=$(fm_control_interrupt_ack_source "$HARNESS")
|
|
376
|
+
INTERRUPT_ACK_LOG=
|
|
377
|
+
INTERRUPT_ACK_RUN=
|
|
378
|
+
case "$INTERRUPT_ACK_SOURCE" in
|
|
379
|
+
muse-session-terminal)
|
|
380
|
+
INTERRUPT_ACK_LOG=$(fm_busy_muse_session_log "$STATE" "$ID" 2>/dev/null || true)
|
|
381
|
+
[ -n "$INTERRUPT_ACK_LOG" ] || return 0
|
|
382
|
+
INTERRUPT_ACK_RUN=$(fm_busy_muse_active_run_id "$INTERRUPT_ACK_LOG" 2>/dev/null || true)
|
|
383
|
+
;;
|
|
384
|
+
esac
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
interrupt_cancel_claim() {
|
|
388
|
+
local elapsed=0 terminal=
|
|
389
|
+
case "$INTERRUPT_ACK_SOURCE:$INTERRUPT_ACK_RUN" in
|
|
390
|
+
muse-session-terminal:?*) ;;
|
|
391
|
+
*) printf 'unconfirmed'; return 0 ;;
|
|
392
|
+
esac
|
|
393
|
+
while :; do
|
|
394
|
+
terminal=$(fm_busy_muse_run_terminal "$INTERRUPT_ACK_LOG" "$INTERRUPT_ACK_RUN" 2>/dev/null || true)
|
|
395
|
+
case "$terminal" in
|
|
396
|
+
cancelled) printf 'confirmed'; return 0 ;;
|
|
397
|
+
?*) printf 'unconfirmed'; return 0 ;;
|
|
398
|
+
esac
|
|
399
|
+
awk -v e="$elapsed" -v t="$SETTLE_WAIT" 'BEGIN{exit !(e < t)}' || break
|
|
400
|
+
sleep "$POLL"
|
|
401
|
+
elapsed=$(awk -v e="$elapsed" -v p="$POLL" 'BEGIN{printf "%.3f", e + p}')
|
|
402
|
+
done
|
|
403
|
+
printf 'unconfirmed'
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
# deliver_interrupt: deliver and observe the strongest adapter-owned
|
|
407
|
+
# cancellation claim available after delivery.
|
|
408
|
+
deliver_interrupt() {
|
|
409
|
+
local cancel
|
|
410
|
+
prepare_interrupt_ack
|
|
411
|
+
send_interrupt_keys
|
|
412
|
+
cancel=$(interrupt_cancel_claim)
|
|
413
|
+
printf '%s' "$cancel"
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
verify_interrupt_running() {
|
|
417
|
+
local proof after
|
|
418
|
+
fm_backend_target_exists "$BACKEND" "$T" "$LABEL" \
|
|
419
|
+
|| die "task $ID's endpoint disappeared while interrupting it; no further control action is safe"
|
|
420
|
+
proof=endpoint
|
|
421
|
+
if fm_control_backend_state_verified "$BACKEND"; then
|
|
422
|
+
# An interrupt cancels a turn; it must never have stopped the agent. This
|
|
423
|
+
# is the postcondition that separates a landed interrupt from an accident.
|
|
424
|
+
after=$(agent_state)
|
|
425
|
+
[ "$after" = alive ] \
|
|
426
|
+
|| die "task $ID's agent is '$after' after its interrupt key; an interrupt must leave the agent running"
|
|
427
|
+
proof=agent-alive
|
|
428
|
+
fi
|
|
429
|
+
printf '%s' "$proof"
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
do_interrupt() {
|
|
433
|
+
local proof cancel
|
|
434
|
+
cancel=$(deliver_interrupt) || return $?
|
|
435
|
+
proof=$(verify_interrupt_running) || return $?
|
|
436
|
+
printf '%s cancel=%s' "$proof" "$cancel"
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
retire_busy_incarnation() {
|
|
440
|
+
if [ -f "$STATE/$ID.busy-gen" ]; then
|
|
441
|
+
"$SCRIPT_DIR/fm-busy-event.sh" retire "$STATE" "$ID" --current-gen >/dev/null 2>&1 || true
|
|
442
|
+
fi
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
# do_exit: stop the running agent, preserving endpoint and worktree. Prints
|
|
446
|
+
# `already-stopped` or `stopped`.
|
|
447
|
+
do_exit() {
|
|
448
|
+
local state cmd verdict cancel interrupt_result=not-needed
|
|
449
|
+
require_state_verified_backend exit
|
|
450
|
+
state=$(agent_state)
|
|
451
|
+
case "$state" in
|
|
452
|
+
dead)
|
|
453
|
+
printf 'already-stopped'
|
|
454
|
+
return 0
|
|
455
|
+
;;
|
|
456
|
+
alive) ;;
|
|
457
|
+
missing) die "task $ID's recorded endpoint is gone, so there is no agent to stop; reconcile the task before any further control action" ;;
|
|
458
|
+
*) die "task $ID's endpoint reads '$state' rather than a positively classified state; refusing to send a lifecycle command into an unattributed endpoint" ;;
|
|
459
|
+
esac
|
|
460
|
+
# A busy agent is interrupted first before the exit command is submitted.
|
|
461
|
+
case "$(busy_verdict)" in
|
|
462
|
+
busy*)
|
|
463
|
+
cancel=$(deliver_interrupt) || return $?
|
|
464
|
+
state=$(agent_state)
|
|
465
|
+
case "$state" in
|
|
466
|
+
dead)
|
|
467
|
+
retire_busy_incarnation
|
|
468
|
+
printf 'stopped'
|
|
469
|
+
return 0
|
|
470
|
+
;;
|
|
471
|
+
alive) interrupt_result="delivered verified=agent-alive cancel=$cancel" ;;
|
|
472
|
+
missing) die "task $ID's recorded endpoint disappeared after interrupt delivery, so exit cannot prove whether the agent stopped" ;;
|
|
473
|
+
*) die "task $ID's endpoint reads '$state' after interrupt delivery rather than a positively classified state; exit cannot prove whether the agent stopped" ;;
|
|
474
|
+
esac
|
|
475
|
+
;;
|
|
476
|
+
esac
|
|
477
|
+
cmd=$(fm_control_exit_command "$HARNESS")
|
|
478
|
+
# The submit verdict is NOT the postcondition here: a successful exit command
|
|
479
|
+
# destroys the composer the verdict is read from, so a post-exit read can
|
|
480
|
+
# legitimately report anything. Only a hard transport failure aborts; the
|
|
481
|
+
# authoritative proof is the agent-state wait below. The retried Enter still
|
|
482
|
+
# matters, because a slash command opens a completion popup on some TUIs that
|
|
483
|
+
# swallows the first Enter.
|
|
484
|
+
verdict=$(fm_backend_send_text_submit "$BACKEND" "$T" "$cmd" "$EXIT_RETRIES" "$POLL" 1.2 "$LABEL") \
|
|
485
|
+
|| die "the exit command could not be sent to task $ID on $BACKEND"
|
|
486
|
+
[ "$verdict" != send-failed ] \
|
|
487
|
+
|| die "the exit command could not be sent to task $ID on $BACKEND"
|
|
488
|
+
state=$(wait_agent_state "$EXIT_WAIT" dead) || {
|
|
489
|
+
die "exit-delivered $ID interrupt=$interrupt_result exit-command=delivered agent-state=$state exit=unconfirmed; the agent did not stop within ${EXIT_WAIT}s"
|
|
490
|
+
}
|
|
491
|
+
# The incarnation is over: retire its busy wiring so no stale record or
|
|
492
|
+
# orphaned generation survives the agent that produced it.
|
|
493
|
+
retire_busy_incarnation
|
|
494
|
+
printf 'stopped'
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
# --- transactional relaunch -------------------------------------------------
|
|
498
|
+
#
|
|
499
|
+
# The transaction's durable record is state/<id>.control-relaunch, with the
|
|
500
|
+
# prior metadata and brief preserved beside it. Every failure path runs through
|
|
501
|
+
# relaunch_rollback (an EXIT trap, so a refusal raised deep inside a shared
|
|
502
|
+
# helper is covered too) and leaves either the pre-relaunch durable record or a
|
|
503
|
+
# concrete, named partial state - never a task whose record claims an agent
|
|
504
|
+
# that is not running.
|
|
505
|
+
|
|
506
|
+
JOURNAL="$STATE/$ID.control-relaunch"
|
|
507
|
+
META_PRIOR="$JOURNAL.meta-prior"
|
|
508
|
+
BRIEF_PRIOR="$JOURNAL.brief-prior"
|
|
509
|
+
NOTE_FILE="$JOURNAL.note"
|
|
510
|
+
RELAUNCH_META_PUBLISHED=0
|
|
511
|
+
RELAUNCH_AGENT_CONFIRMED=0
|
|
512
|
+
RELAUNCH_TX=
|
|
513
|
+
RELAUNCH_BRIEF=
|
|
514
|
+
PRIOR_HARNESS=$HARNESS
|
|
515
|
+
PRIOR_RECORDED_HARNESS=$RECORDED_HARNESS
|
|
516
|
+
CONFIG_HARNESS=
|
|
517
|
+
CONFIG_MODEL=
|
|
518
|
+
CONFIG_EFFORT=
|
|
519
|
+
PRIOR_MODEL=
|
|
520
|
+
PRIOR_EFFORT=
|
|
521
|
+
TARGET_HARNESS=$HARNESS
|
|
522
|
+
TARGET_MODEL=
|
|
523
|
+
TARGET_EFFORT=
|
|
524
|
+
|
|
525
|
+
journal_write() { # <phase> [extra-line]...
|
|
526
|
+
local phase=$1
|
|
527
|
+
shift
|
|
528
|
+
if {
|
|
529
|
+
echo "v1"
|
|
530
|
+
echo "task=$ID"
|
|
531
|
+
echo "phase=$phase"
|
|
532
|
+
echo "ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
533
|
+
echo "backend=$BACKEND"
|
|
534
|
+
echo "endpoint=$T"
|
|
535
|
+
echo "worktree=$WT"
|
|
536
|
+
echo "kind=$KIND"
|
|
537
|
+
echo "from_harness=$PRIOR_RECORDED_HARNESS"
|
|
538
|
+
echo "from_model=$PRIOR_MODEL"
|
|
539
|
+
echo "from_effort=$PRIOR_EFFORT"
|
|
540
|
+
echo "to_harness=$TARGET_HARNESS"
|
|
541
|
+
echo "to_model=$TARGET_MODEL"
|
|
542
|
+
echo "to_effort=$TARGET_EFFORT"
|
|
543
|
+
local line
|
|
544
|
+
for line in "$@"; do
|
|
545
|
+
echo "$line"
|
|
546
|
+
done
|
|
547
|
+
} > "$JOURNAL.tmp" && mv -f "$JOURNAL.tmp" "$JOURNAL"; then
|
|
548
|
+
RELAUNCH_PHASE=$phase
|
|
549
|
+
return 0
|
|
550
|
+
fi
|
|
551
|
+
return 1
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
relaunch_rollback() {
|
|
555
|
+
local state
|
|
556
|
+
[ "$RELAUNCH_ACTIVE" = 1 ] || return 0
|
|
557
|
+
[ "$RELAUNCH_PHASE" != complete ] || return 0
|
|
558
|
+
RELAUNCH_ACTIVE=0
|
|
559
|
+
case "$RELAUNCH_PHASE" in
|
|
560
|
+
checkpoint|noted)
|
|
561
|
+
# The old agent was never touched. Restore the instructions byte-exact so
|
|
562
|
+
# a refused relaunch leaves nothing behind.
|
|
563
|
+
if [ -n "$RELAUNCH_BRIEF" ] && [ -f "$BRIEF_PRIOR" ]; then
|
|
564
|
+
cp -p "$BRIEF_PRIOR" "$RELAUNCH_BRIEF" 2>/dev/null || true
|
|
565
|
+
fi
|
|
566
|
+
journal_write "failed:$RELAUNCH_PHASE" "rollback=instructions-restored" || true
|
|
567
|
+
echo "error: relaunch of $ID was refused before its agent was touched; nothing changed" >&2
|
|
568
|
+
;;
|
|
569
|
+
stopping)
|
|
570
|
+
state=$(agent_state 2>/dev/null || printf unknown)
|
|
571
|
+
case "$state" in
|
|
572
|
+
alive)
|
|
573
|
+
if [ -n "$RELAUNCH_BRIEF" ] && [ -f "$BRIEF_PRIOR" ]; then
|
|
574
|
+
cp -p "$BRIEF_PRIOR" "$RELAUNCH_BRIEF" 2>/dev/null || true
|
|
575
|
+
fi
|
|
576
|
+
journal_write "failed:$RELAUNCH_PHASE" "rollback=instructions-restored-agent-alive" || true
|
|
577
|
+
echo "error: relaunch of $ID failed while stopping the old agent, which is still running; its original instructions were restored" >&2
|
|
578
|
+
;;
|
|
579
|
+
dead)
|
|
580
|
+
journal_write "failed:$RELAUNCH_PHASE" "rollback=prior-record-kept-agent-dead" || true
|
|
581
|
+
echo "error: $ID's agent stopped but relaunch did not reach replacement launch; no agent is running, and its work plus progress note are preserved at $WT" >&2
|
|
582
|
+
;;
|
|
583
|
+
*)
|
|
584
|
+
journal_write "failed:$RELAUNCH_PHASE" "rollback=none-agent-state-$state" || true
|
|
585
|
+
echo "error: relaunch of $ID failed while stopping the old agent and its state is '$state'; the durable record and progress note were retained for recovery" >&2
|
|
586
|
+
;;
|
|
587
|
+
esac
|
|
588
|
+
;;
|
|
589
|
+
exited|launching)
|
|
590
|
+
if [ "$RELAUNCH_AGENT_CONFIRMED" = 1 ]; then
|
|
591
|
+
journal_write "failed:$RELAUNCH_PHASE" "rollback=none-new-agent-confirmed" || true
|
|
592
|
+
echo "error: $ID's replacement is running on $TARGET_HARNESS, but transaction completion could not be persisted; its published record was retained for reconciliation" >&2
|
|
593
|
+
elif [ "$RELAUNCH_META_PUBLISHED" = 1 ] \
|
|
594
|
+
|| { [ -n "$RELAUNCH_TX" ] \
|
|
595
|
+
&& [ "$(fm_meta_get "$META" control_relaunch_tx)" = "$RELAUNCH_TX" ]; }; then
|
|
596
|
+
# The launch owner published the new incarnation's record. Leaving it
|
|
597
|
+
# in place is the honest state: the task is now recorded on the new
|
|
598
|
+
# harness with no agent confirmed, which is exactly what recovery
|
|
599
|
+
# reconciles. Rewriting it back to the old harness would be a second,
|
|
600
|
+
# worse inaccuracy.
|
|
601
|
+
journal_write "failed:$RELAUNCH_PHASE" "rollback=none-new-record-kept" || true
|
|
602
|
+
echo "error: $ID was relaunched on $TARGET_HARNESS but no running agent could be confirmed; its work is preserved at $WT" >&2
|
|
603
|
+
else
|
|
604
|
+
journal_write "failed:$RELAUNCH_PHASE" "rollback=prior-record-kept" || true
|
|
605
|
+
echo "error: $ID's agent was stopped but the replacement did not launch; no agent is running, and its work plus the recorded progress note are preserved at $WT" >&2
|
|
606
|
+
fi
|
|
607
|
+
;;
|
|
608
|
+
esac
|
|
609
|
+
return 0
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
resolve_relaunch_profile() {
|
|
613
|
+
PRIOR_HARNESS=$HARNESS
|
|
614
|
+
PRIOR_RECORDED_HARNESS=$RECORDED_HARNESS
|
|
615
|
+
PRIOR_MODEL=$(fm_meta_get "$META" model)
|
|
616
|
+
PRIOR_EFFORT=$(fm_meta_get "$META" effort)
|
|
617
|
+
[ -n "$PRIOR_MODEL" ] || PRIOR_MODEL=default
|
|
618
|
+
[ -n "$PRIOR_EFFORT" ] || PRIOR_EFFORT=default
|
|
619
|
+
if [ "$HARNESS_SET" = 0 ] \
|
|
620
|
+
&& [ "$PRIOR_RECORDED_HARNESS" != "$PRIOR_HARNESS" ]; then
|
|
621
|
+
die "task $ID records harness '$PRIOR_RECORDED_HARNESS', whose original launch command cannot be reconstructed from its recorded basename; relaunching without --harness would substitute the canonical adapter '$PRIOR_HARNESS' for the command actually running. Pass an explicit --harness to choose the replacement runtime deliberately"
|
|
622
|
+
fi
|
|
623
|
+
CONFIG_HARNESS=
|
|
624
|
+
CONFIG_MODEL=
|
|
625
|
+
CONFIG_EFFORT=
|
|
626
|
+
if [ "$KIND" = secondmate ]; then
|
|
627
|
+
# A secondmate's harness, model, and effort are a durable configured pin
|
|
628
|
+
# that every respawn re-resolves (the secondmate-provisioning contract), so
|
|
629
|
+
# a relaunch with no explicit harness picks up a newly configured one
|
|
630
|
+
# instead of freezing whatever this incarnation happens to run. Crewmates
|
|
631
|
+
# and scouts deliberately do NOT resolve config here: their harness comes
|
|
632
|
+
# from firstmate's own dispatch-profile judgment at intake, and silently
|
|
633
|
+
# re-resolving it would bypass that consultation.
|
|
634
|
+
CONFIG_HARNESS=$("$SCRIPT_DIR/fm-harness.sh" secondmate 2>/dev/null || true)
|
|
635
|
+
CONFIG_MODEL=$("$SCRIPT_DIR/fm-harness.sh" secondmate-model 2>/dev/null || true)
|
|
636
|
+
CONFIG_EFFORT=$("$SCRIPT_DIR/fm-harness.sh" secondmate-effort 2>/dev/null || true)
|
|
637
|
+
case "$CONFIG_EFFORT" in
|
|
638
|
+
''|low|medium|high|xhigh|max) ;;
|
|
639
|
+
*)
|
|
640
|
+
echo "warning: config/secondmate-harness effort token '$CONFIG_EFFORT' is not one of low, medium, high, xhigh, max; ignoring" >&2
|
|
641
|
+
CONFIG_EFFORT=
|
|
642
|
+
;;
|
|
643
|
+
esac
|
|
644
|
+
fi
|
|
645
|
+
if [ "$HARNESS_SET" = 1 ]; then
|
|
646
|
+
fm_control_harness_supported "$NEW_HARNESS" \
|
|
647
|
+
|| die "'$NEW_HARNESS' is not a verified harness; fm-control refuses to relaunch onto an adapter with no verified control or launch mechanics"
|
|
648
|
+
TARGET_HARNESS=$NEW_HARNESS
|
|
649
|
+
elif [ "$HARNESS_SET" = 0 ] && [ -n "$CONFIG_HARNESS" ]; then
|
|
650
|
+
fm_control_harness_supported "$CONFIG_HARNESS" \
|
|
651
|
+
|| die "the configured secondmate harness '$CONFIG_HARNESS' is not verified; fm-control refuses to relaunch onto an adapter with no verified control or launch mechanics"
|
|
652
|
+
TARGET_HARNESS=$CONFIG_HARNESS
|
|
653
|
+
else
|
|
654
|
+
TARGET_HARNESS=$PRIOR_HARNESS
|
|
655
|
+
fi
|
|
656
|
+
# The launch owner refuses an adapter that cannot run this task's kind, but it
|
|
657
|
+
# is only reached after the old agent has been stopped. Asking the same
|
|
658
|
+
# capability table here keeps that refusal on the pre-stop side of the
|
|
659
|
+
# transaction, where nothing has changed yet.
|
|
660
|
+
fm_control_harness_supports_kind "$TARGET_HARNESS" "$KIND" \
|
|
661
|
+
|| die "'$TARGET_HARNESS' is not verified to run a $KIND task, so relaunching $ID onto it would stop the running agent for a launch that must be refused; choose an adapter verified for this kind"
|
|
662
|
+
# A model or effort chosen for the previous harness does not transfer to a
|
|
663
|
+
# different one, so an explicit harness change resets both axes unless the
|
|
664
|
+
# caller names them too.
|
|
665
|
+
if [ "$MODEL_SET" = 1 ]; then
|
|
666
|
+
TARGET_MODEL=$NEW_MODEL
|
|
667
|
+
elif [ "$HARNESS_SET" = 0 ] && [ -n "$CONFIG_HARNESS" ]; then
|
|
668
|
+
TARGET_MODEL=${CONFIG_MODEL:-default}
|
|
669
|
+
elif [ "$TARGET_HARNESS" = "$PRIOR_HARNESS" ]; then
|
|
670
|
+
TARGET_MODEL=$PRIOR_MODEL
|
|
671
|
+
else
|
|
672
|
+
TARGET_MODEL=default
|
|
673
|
+
fi
|
|
674
|
+
if [ "$EFFORT_SET" = 1 ]; then
|
|
675
|
+
TARGET_EFFORT=$NEW_EFFORT
|
|
676
|
+
elif [ "$HARNESS_SET" = 0 ] && [ -n "$CONFIG_HARNESS" ]; then
|
|
677
|
+
TARGET_EFFORT=${CONFIG_EFFORT:-default}
|
|
678
|
+
elif [ "$TARGET_HARNESS" = "$PRIOR_HARNESS" ]; then
|
|
679
|
+
TARGET_EFFORT=$PRIOR_EFFORT
|
|
680
|
+
else
|
|
681
|
+
TARGET_EFFORT=default
|
|
682
|
+
fi
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
# safe_checkpoint: prove, before anything is stopped, that the work a relaunch
|
|
686
|
+
# must preserve is actually there and recoverable afterwards. Fills
|
|
687
|
+
# CHECKPOINT_LINES with the journal lines describing what it proved, and
|
|
688
|
+
# refuses outright when any of it cannot be established.
|
|
689
|
+
CHECKPOINT_LINES=()
|
|
690
|
+
safe_checkpoint() {
|
|
691
|
+
local wt_real wt_top wt_top_real head head_ref head_ref_status status_output dirty children marker child_meta
|
|
692
|
+
CHECKPOINT_LINES=()
|
|
693
|
+
[ -n "$WT" ] || die "task $ID has no recorded worktree; refusing to relaunch without a recorded local copy to preserve"
|
|
694
|
+
[ -d "$WT" ] || die "task $ID's recorded worktree $WT is missing; refusing to relaunch and lose track of its work"
|
|
695
|
+
wt_real=$(cd "$WT" 2>/dev/null && pwd -P) || die "task $ID's recorded worktree $WT cannot be resolved"
|
|
696
|
+
wt_top=$(git -C "$WT" rev-parse --show-toplevel 2>/dev/null) \
|
|
697
|
+
|| die "task $ID's recorded worktree $WT is not a git worktree; refusing to relaunch without a checkout whose unlanded work can be accounted for"
|
|
698
|
+
wt_top_real=$(cd "$wt_top" 2>/dev/null && pwd -P) || wt_top_real=$wt_top
|
|
699
|
+
[ "$wt_real" = "$wt_top_real" ] \
|
|
700
|
+
|| die "task $ID's recorded worktree $WT is not a worktree root (root is $wt_top); refusing to relaunch against an ambiguous checkout"
|
|
701
|
+
if head=$(git -C "$WT" rev-parse --verify HEAD 2>/dev/null); then
|
|
702
|
+
:
|
|
703
|
+
elif head_ref=$(git -C "$WT" symbolic-ref -q HEAD 2>/dev/null); then
|
|
704
|
+
if git -C "$WT" show-ref --verify --quiet "$head_ref" 2>/dev/null; then
|
|
705
|
+
die "task $ID's worktree HEAD exists but cannot be resolved; refusing to relaunch from an unreadable checkout"
|
|
706
|
+
else
|
|
707
|
+
head_ref_status=$?
|
|
708
|
+
[ "$head_ref_status" -eq 1 ] \
|
|
709
|
+
|| die "task $ID's worktree HEAD cannot be inspected; refusing to relaunch from an unreadable checkout"
|
|
710
|
+
head=unborn
|
|
711
|
+
fi
|
|
712
|
+
else
|
|
713
|
+
die "task $ID's worktree HEAD cannot be inspected; refusing to relaunch from an unreadable checkout"
|
|
714
|
+
fi
|
|
715
|
+
status_output=$(git -C "$WT" status --porcelain 2>/dev/null) \
|
|
716
|
+
|| die "task $ID's worktree status cannot be inspected; refusing to relaunch without accounting for local changes"
|
|
717
|
+
if [ -n "$status_output" ]; then
|
|
718
|
+
dirty=yes
|
|
719
|
+
else
|
|
720
|
+
dirty=no
|
|
721
|
+
fi
|
|
722
|
+
CHECKPOINT_LINES+=("worktree_head=$head" "worktree_dirty=$dirty")
|
|
723
|
+
if [ "$KIND" = secondmate ]; then
|
|
724
|
+
# A secondmate's own crewmates outlive its relaunch: they run in their own
|
|
725
|
+
# endpoints, and the relaunched secondmate reconciles them from its home's
|
|
726
|
+
# durable records at startup. The checkpoint proves those records are
|
|
727
|
+
# readable BEFORE the agent stops, so a relaunch can never strand child
|
|
728
|
+
# work behind an unreadable home.
|
|
729
|
+
marker=$(cat "$WT/.fm-secondmate-home" 2>/dev/null || true)
|
|
730
|
+
[ "$marker" = "$ID" ] \
|
|
731
|
+
|| die "task $ID's home $WT is not marked as its own seeded secondmate home (marker: ${marker:-none}); refusing to relaunch"
|
|
732
|
+
[ -d "$WT/state" ] \
|
|
733
|
+
|| die "secondmate $ID's home has no readable state directory, so its child work cannot be accounted for; refusing to relaunch"
|
|
734
|
+
find "$WT/state" -mindepth 1 -maxdepth 1 -print >/dev/null 2>&1 \
|
|
735
|
+
|| die "secondmate $ID's child records cannot be traversed; refusing to relaunch"
|
|
736
|
+
children=0
|
|
737
|
+
for child_meta in "$WT/state"/*.meta; do
|
|
738
|
+
if [ ! -e "$child_meta" ] && [ ! -L "$child_meta" ]; then
|
|
739
|
+
continue
|
|
740
|
+
fi
|
|
741
|
+
if [ ! -f "$child_meta" ] || [ -L "$child_meta" ] \
|
|
742
|
+
|| ! cat "$child_meta" >/dev/null 2>&1; then
|
|
743
|
+
die "secondmate $ID's child record $child_meta is not a readable regular file; refusing to relaunch"
|
|
744
|
+
fi
|
|
745
|
+
children=$((children + 1))
|
|
746
|
+
done
|
|
747
|
+
CHECKPOINT_LINES+=("children=$children")
|
|
748
|
+
fi
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
# record_note: put the required progress note somewhere durable, and - for a
|
|
752
|
+
# ship or scout, whose only record of the interrupted reasoning is the
|
|
753
|
+
# conversation about to be discarded - into the instructions the replacement
|
|
754
|
+
# actually reads. A secondmate's charter is a durable standing document and is
|
|
755
|
+
# never rewritten: a secondmate reconciles its own home's records at startup,
|
|
756
|
+
# so the note stays parent-side audit evidence.
|
|
757
|
+
record_note() {
|
|
758
|
+
local stamp
|
|
759
|
+
[ -n "$NOTE" ] || return 0
|
|
760
|
+
stamp=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
761
|
+
printf '%s\n' "$NOTE" > "$NOTE_FILE"
|
|
762
|
+
case "$KIND" in
|
|
763
|
+
ship|scout)
|
|
764
|
+
cp -p "$RELAUNCH_BRIEF" "$BRIEF_PRIOR" \
|
|
765
|
+
|| die "could not preserve task $ID's instructions before recording the progress note"
|
|
766
|
+
{
|
|
767
|
+
echo
|
|
768
|
+
echo "## Progress note ($stamp)"
|
|
769
|
+
echo
|
|
770
|
+
echo "This task was relaunched. Continue from here; the local copy and every"
|
|
771
|
+
echo "uncommitted change are exactly as the previous worker left them."
|
|
772
|
+
echo
|
|
773
|
+
echo "First, check your instruction inbox: list $STATE/$ID.inbox/*.msg, act on"
|
|
774
|
+
echo "each message in numeric order, then mv each handled file into"
|
|
775
|
+
echo "$STATE/$ID.inbox/handled/. A steer sent before the relaunch survives there."
|
|
776
|
+
echo
|
|
777
|
+
printf '%s\n' "$NOTE"
|
|
778
|
+
} >> "$RELAUNCH_BRIEF" \
|
|
779
|
+
|| die "could not append the progress note to task $ID's instructions"
|
|
780
|
+
;;
|
|
781
|
+
esac
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
do_relaunch() {
|
|
785
|
+
local exit_result state note_line
|
|
786
|
+
local -a spawn_args
|
|
787
|
+
|
|
788
|
+
require_state_verified_backend relaunch
|
|
789
|
+
resolve_relaunch_profile
|
|
790
|
+
|
|
791
|
+
case "$KIND" in
|
|
792
|
+
ship|scout)
|
|
793
|
+
RELAUNCH_BRIEF="$DATA/$ID/brief.md"
|
|
794
|
+
[ -f "$RELAUNCH_BRIEF" ] \
|
|
795
|
+
|| die "task $ID has no instructions at $RELAUNCH_BRIEF; refusing to relaunch a worker with nothing to work from"
|
|
796
|
+
[ "$NOTE_SET" = 1 ] && [ -n "$NOTE" ] \
|
|
797
|
+
|| die "relaunch of a $KIND task requires --note (or --note-file): the replacement worker inherits the local copy but none of the conversation, so it must be told what happened"
|
|
798
|
+
;;
|
|
799
|
+
secondmate)
|
|
800
|
+
# The charter in the secondmate's own home is its instruction source and
|
|
801
|
+
# stays untouched.
|
|
802
|
+
RELAUNCH_BRIEF=
|
|
803
|
+
;;
|
|
804
|
+
*)
|
|
805
|
+
die "task $ID records kind '$KIND', which has no defined relaunch shape"
|
|
806
|
+
;;
|
|
807
|
+
esac
|
|
808
|
+
|
|
809
|
+
if [ -n "$NOTE" ]; then
|
|
810
|
+
note_line="note_file=$NOTE_FILE"
|
|
811
|
+
else
|
|
812
|
+
note_line="note=none"
|
|
813
|
+
fi
|
|
814
|
+
safe_checkpoint
|
|
815
|
+
cp -p "$META" "$META_PRIOR" || die "could not preserve task $ID's durable record before relaunching"
|
|
816
|
+
RELAUNCH_ACTIVE=1
|
|
817
|
+
journal_write checkpoint "${CHECKPOINT_LINES[@]}" "$note_line"
|
|
818
|
+
|
|
819
|
+
record_note
|
|
820
|
+
journal_write noted "${CHECKPOINT_LINES[@]}" "$note_line"
|
|
821
|
+
|
|
822
|
+
journal_write stopping "${CHECKPOINT_LINES[@]}" "$note_line"
|
|
823
|
+
exit_result=$(do_exit)
|
|
824
|
+
journal_write exited "${CHECKPOINT_LINES[@]}" "$note_line" "exit_result=$exit_result"
|
|
825
|
+
|
|
826
|
+
# The launch owner (fm-spawn --relaunch) clears the previous incarnation's
|
|
827
|
+
# per-task harness wiring before arming the new one, so nothing to do here.
|
|
828
|
+
RELAUNCH_TX="${BASHPID:-$$}.$(date -u +%Y%m%dT%H%M%SZ).$RANDOM"
|
|
829
|
+
journal_write launching "${CHECKPOINT_LINES[@]}" "$note_line" "relaunch_tx=$RELAUNCH_TX"
|
|
830
|
+
spawn_args=("$ID" --relaunch --harness "$TARGET_HARNESS")
|
|
831
|
+
[ "$TARGET_MODEL" = default ] || spawn_args+=(--model "$TARGET_MODEL")
|
|
832
|
+
[ "$TARGET_EFFORT" = default ] || spawn_args+=(--effort "$TARGET_EFFORT")
|
|
833
|
+
if FM_CONTROL_RELAUNCH_TX="$RELAUNCH_TX" \
|
|
834
|
+
"$SCRIPT_DIR/fm-spawn.sh" "${spawn_args[@]}" >/dev/null; then
|
|
835
|
+
RELAUNCH_META_PUBLISHED=1
|
|
836
|
+
else
|
|
837
|
+
[ "$(fm_meta_get "$META" control_relaunch_tx)" != "$RELAUNCH_TX" ] \
|
|
838
|
+
|| RELAUNCH_META_PUBLISHED=1
|
|
839
|
+
die "the replacement agent for $ID could not be launched on $TARGET_HARNESS"
|
|
840
|
+
fi
|
|
841
|
+
|
|
842
|
+
state=$(wait_agent_state "$LAUNCH_WAIT" alive) || {
|
|
843
|
+
die "the replacement agent for $ID did not come up within ${LAUNCH_WAIT}s (endpoint reads '$state')"
|
|
844
|
+
}
|
|
845
|
+
RELAUNCH_AGENT_CONFIRMED=1
|
|
846
|
+
|
|
847
|
+
journal_write complete "${CHECKPOINT_LINES[@]}" "$note_line" "exit_result=$exit_result"
|
|
848
|
+
RELAUNCH_ACTIVE=0
|
|
849
|
+
echo "relaunched $ID harness=$TARGET_HARNESS from=$PRIOR_RECORDED_HARNESS model=$TARGET_MODEL effort=$TARGET_EFFORT backend=$BACKEND endpoint=$T worktree=$WT"
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
# --- verbs ------------------------------------------------------------------
|
|
853
|
+
|
|
854
|
+
case "$VERB" in
|
|
855
|
+
interrupt)
|
|
856
|
+
state=$(agent_state)
|
|
857
|
+
case "$state" in
|
|
858
|
+
alive) ;;
|
|
859
|
+
unverified)
|
|
860
|
+
# No recovery-grade classifier on this backend. Interrupt is
|
|
861
|
+
# non-destructive and its endpoint-existence postcondition is still
|
|
862
|
+
# real, so it proceeds - the printed proof names exactly what was
|
|
863
|
+
# verified rather than implying more.
|
|
864
|
+
;;
|
|
865
|
+
dead|missing) die "no agent is running at task $ID's recorded endpoint (state: $state); there is nothing to interrupt" ;;
|
|
866
|
+
*) die "task $ID's endpoint reads '$state' rather than a positively classified state; refusing to send a lifecycle key into an unattributed endpoint" ;;
|
|
867
|
+
esac
|
|
868
|
+
proof=$(do_interrupt)
|
|
869
|
+
echo "interrupt-delivered $ID harness=$HARNESS backend=$BACKEND verified=$proof"
|
|
870
|
+
;;
|
|
871
|
+
exit)
|
|
872
|
+
result=$(do_exit)
|
|
873
|
+
echo "$result $ID harness=$HARNESS backend=$BACKEND endpoint=$T worktree=$WT"
|
|
874
|
+
;;
|
|
875
|
+
relaunch)
|
|
876
|
+
do_relaunch
|
|
877
|
+
;;
|
|
878
|
+
esac
|