@zerwiz/ymir 0.1.4 → 0.1.5
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/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 +290 -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 +50 -0
- package/.agents/config/agents.yaml.example +72 -0
- package/.agents/config/crew-dispatch.json +22 -0
- package/.agents/config/cron.yaml +9 -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/config/tailscale-sync.yaml +27 -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/kaia.engram +0 -0
- package/.agents/memory/kaia.engram-shm +0 -0
- package/.agents/memory/kaia.engram-wal +0 -0
- package/.agents/memory/runes_audit.md +5 -0
- package/.agents/memory/well/episodes.jsonl +367 -0
- package/.agents/memory/well/workspace.jsonl +27 -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 +111 -0
- package/.agents/migrations/0004-hoard-and-realms.sh +104 -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 +158 -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 +673 -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 +496 -0
- package/.agents/skills/galdr-ymirsystem/assets/installation.md +571 -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 +161 -0
- package/.agents/skills/galdr-ymirsystem/assets/nornir-jobs.md +377 -0
- package/.agents/skills/galdr-ymirsystem/assets/norse-naming.md +325 -0
- package/.agents/skills/galdr-ymirsystem/assets/odrerir-hall.md +129 -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 +96 -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 +175 -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 +360 -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 +70 -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 +52 -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 +34 -0
- package/.agents/skills/ymir-host/assets/desktop.md +36 -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 +454 -0
- package/CHANGELOG.md +881 -0
- package/LICENSE +1 -1
- package/NOTICE +63 -0
- package/README.md +113 -59
- 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 +65 -0
- package/RULES/05-platforms.md +67 -0
- package/RULES/06-append-only.md +58 -0
- package/RULES/07-config.md +45 -0
- package/RULES/08-delivery-gate.md +75 -0
- package/RULES/README.md +20 -0
- package/bin/README.md +107 -0
- package/bin/a2a-mcp.sh +98 -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 +233 -0
- package/bin/apodex-smoke-test.sh +92 -0
- package/bin/bifrost-bridge.sh +112 -0
- package/bin/bifrost-ingress.sh +77 -0
- package/bin/bootstrap-macos.sh +107 -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 +38 -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-guard.sh +165 -0
- package/bin/crash-sense.sh +160 -0
- package/bin/desktop-place.sh +224 -0
- package/bin/docs-guard.sh +39 -0
- package/bin/editor-place.sh +207 -0
- package/bin/eindri-acclaim.sh +34 -0
- package/bin/eindri-control.sh +28 -0
- package/bin/eindri-role.sh +83 -0
- package/bin/eindri-seen.sh +41 -0
- package/bin/eindri-send.sh +15 -0
- package/bin/eindri-start.sh +85 -0
- package/bin/eindri-watch.sh +57 -0
- package/bin/einherjar-spawn.sh +576 -0
- package/bin/eir-doctor.sh +112 -0
- package/bin/erindi-brief.sh +271 -0
- package/bin/fleet-apply.sh +68 -0
- package/bin/github-deploy.sh +81 -0
- package/bin/gjallarhorn-expose.sh +102 -0
- package/bin/gjallarhorn-notify.sh +58 -0
- package/bin/gjallarhorn-purge.sh +54 -0
- package/bin/gjallarhorn-tunnel.sh +72 -0
- package/bin/gleipnir-lock-lib.sh +284 -0
- package/bin/groa-update.sh +122 -0
- package/bin/hall-snapshot.sh +92 -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 +431 -0
- package/bin/hermes-ensure.sh +88 -0
- package/bin/hoard-lib.sh +25 -0
- package/bin/hodd.sh +78 -0
- package/bin/host-sense.sh +199 -0
- package/bin/huginn-research-worker.sh +108 -0
- package/bin/local-model-lock.sh +51 -0
- package/bin/mimir-bridge.py +226 -0
- package/bin/mimir-bridge.sh +87 -0
- package/bin/mimir-ingest.sh +131 -0
- package/bin/mimir.sh +113 -0
- package/bin/mjollnir-webhook.sh +59 -0
- package/bin/mjollnir.sh +85 -0
- package/bin/model-hardware.sh +82 -0
- package/bin/model-resolve.sh +147 -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-memory-housekeeping.sh +114 -0
- package/bin/nornir-job-observer.sh +166 -0
- package/bin/nornir-job-skillopt-sleep.sh +76 -0
- package/bin/omarchy-hook-install.sh +60 -0
- package/bin/omarchy-install.sh +148 -0
- package/bin/omarchy-plugins.sh +174 -0
- package/bin/omarchy-sense.sh +149 -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-seat.sh +63 -0
- package/bin/prereq-ensure.sh +166 -0
- package/bin/private-guard.sh +38 -0
- package/bin/project-git.sh +55 -0
- package/bin/public-guard.sh +70 -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 +91 -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 +90 -0
- package/bin/smidja-observe.sh +86 -0
- package/bin/syn-arm-pretool-check.sh +57 -0
- package/bin/syn-asset-pretool-check.sh +76 -0
- package/bin/syn-cd-pretool-check.sh +28 -0
- package/bin/syn-guard-pretool-check.sh +83 -0
- package/bin/syn-turnend-guard.sh +36 -0
- package/bin/syn-watch-arm.sh +99 -0
- package/bin/tailscale-sync.sh +190 -0
- package/bin/telegram-bot.sh +69 -0
- package/bin/toolchain.sh +74 -0
- package/bin/utgard.sh +111 -0
- package/bin/valhalla.sh +115 -0
- package/bin/valknut-load.sh +260 -0
- package/bin/vor-crew-state.sh +124 -0
- package/bin/wedge-notify.sh +47 -0
- package/bin/workspace-provision.sh +80 -0
- package/bin/workspace-rag.sh +150 -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 +641 -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-platform.sh +348 -0
- package/bin/ymir-say.sh +97 -0
- package/bin/ymir-setup-auth.sh +108 -0
- package/bin/ymir-validate.sh +173 -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 +1056 -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 +44 -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 +210 -0
- package/scripts/start.sh +167 -0
- package/scripts/stop.sh +113 -0
- package/install.sh +0 -35
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# tests/fm-backend-herdr-eventwait-smoke.test.sh - REAL-herdr smoke test for the
|
|
3
|
+
# native pane.agent_status_changed push escalation (fm_backend_herdr_wait_transition,
|
|
4
|
+
# bin/backends/herdr.sh, and its raw-socket reader bin/backends/herdr-eventwait.py).
|
|
5
|
+
# It drives a real idle->blocked transition in an ISOLATED, never-default herdr
|
|
6
|
+
# lab session and asserts the subscriber returns that transition sub-second and
|
|
7
|
+
# that the watcher's handle_push_transition lands a stale record in a scratch
|
|
8
|
+
# state/.wake-queue. Skips cleanly when herdr, jq, or python3 is missing.
|
|
9
|
+
#
|
|
10
|
+
# Safety (2026-07-02 incident, tests/herdr-test-safety.sh): cleanup uses ONLY
|
|
11
|
+
# herdr_safe_stop_and_delete on a private fm-lab-* session, never a bare/ambient
|
|
12
|
+
# `herdr server stop`. Every lifecycle op goes through bin/fm-herdr-lab.sh, which
|
|
13
|
+
# refuses the default session and verifies the fleet-state tripwire.
|
|
14
|
+
set -u
|
|
15
|
+
|
|
16
|
+
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
17
|
+
|
|
18
|
+
fail() { printf 'not ok - %s\n' "$1" >&2; cleanup_all; exit 1; }
|
|
19
|
+
pass() { printf 'ok - %s\n' "$1"; }
|
|
20
|
+
|
|
21
|
+
command -v herdr >/dev/null 2>&1 || { echo "skip: herdr not found"; exit 0; }
|
|
22
|
+
command -v jq >/dev/null 2>&1 || { echo "skip: jq not found (required by the herdr adapter)"; exit 0; }
|
|
23
|
+
command -v python3 >/dev/null 2>&1 || { echo "skip: python3 not found (required by the event subscriber)"; exit 0; }
|
|
24
|
+
|
|
25
|
+
# shellcheck source=tests/herdr-test-safety.sh
|
|
26
|
+
. "$ROOT/tests/herdr-test-safety.sh"
|
|
27
|
+
|
|
28
|
+
# This suite runs against its own isolated lab session, so a Herdr pane
|
|
29
|
+
# inherited from the terminal it was launched in must not follow spawn into it
|
|
30
|
+
# as a cross-session parent identity (tests/herdr-test-safety.sh).
|
|
31
|
+
herdr_forget_inherited_pane
|
|
32
|
+
|
|
33
|
+
SESSION="fm-lab-eventwait-smoke-$$"
|
|
34
|
+
export HERDR_SESSION="$SESSION"
|
|
35
|
+
SCRATCH=
|
|
36
|
+
cleanup_all() {
|
|
37
|
+
[ -n "$SCRATCH" ] && rm -rf "$SCRATCH"
|
|
38
|
+
herdr_safe_stop_and_delete "$SESSION"
|
|
39
|
+
}
|
|
40
|
+
trap cleanup_all EXIT
|
|
41
|
+
fm_herdr_lab_prepare "$SESSION" || fail "could not prepare the isolated Herdr lab session"
|
|
42
|
+
|
|
43
|
+
# The dispatcher is a separately linted production boundary. Its dynamic
|
|
44
|
+
# adapter source edges stop at each independently linted canonical adapter.
|
|
45
|
+
# shellcheck source=/dev/null
|
|
46
|
+
. "$ROOT/bin/fm-backend.sh"
|
|
47
|
+
fm_backend_source herdr || fail "fm_backend_source herdr failed"
|
|
48
|
+
|
|
49
|
+
HERDR_VERSION=$(herdr --version 2>/dev/null | head -1)
|
|
50
|
+
|
|
51
|
+
# --- real capability gate ----------------------------------------------------
|
|
52
|
+
|
|
53
|
+
if ! fm_backend_herdr_events_capable "$SESSION"; then
|
|
54
|
+
echo "skip: this herdr build is below the events.subscribe capability (protocol < 16 or events surface absent)"
|
|
55
|
+
cleanup_all
|
|
56
|
+
trap - EXIT
|
|
57
|
+
exit 0
|
|
58
|
+
fi
|
|
59
|
+
pass "real herdr ($HERDR_VERSION): events.subscribe capability gate passes (protocol >= 16, events surface present in api schema)"
|
|
60
|
+
|
|
61
|
+
# --- container + a real task pane in the isolated session --------------------
|
|
62
|
+
|
|
63
|
+
CONTAINER_RAW=$(fm_backend_herdr_container_ensure /tmp) || fail "container_ensure failed"
|
|
64
|
+
CONTAINER=${CONTAINER_RAW%%$'\t'*}
|
|
65
|
+
SEEDED_TAB_ID=${CONTAINER_RAW#*$'\t'}
|
|
66
|
+
IDS=$(fm_backend_herdr_create_task "$CONTAINER" "fm-evwait1" /tmp "$SEEDED_TAB_ID") || fail "create_task failed"
|
|
67
|
+
read -r _TAB_ID PANE_ID <<EOF
|
|
68
|
+
$IDS
|
|
69
|
+
EOF
|
|
70
|
+
[ -n "$PANE_ID" ] || fail "create_task did not return a pane id"
|
|
71
|
+
TARGET="$SESSION:$PANE_ID"
|
|
72
|
+
|
|
73
|
+
# scratch firstmate state so window_to_task and the wake queue resolve
|
|
74
|
+
SCRATCH=$(mktemp -d "${TMPDIR:-/tmp}/fm-evwait.XXXXXX")
|
|
75
|
+
STATE="$SCRATCH/state"; mkdir -p "$STATE"
|
|
76
|
+
cat > "$STATE/evwait1.meta" <<EOF
|
|
77
|
+
window=$TARGET
|
|
78
|
+
backend=herdr
|
|
79
|
+
kind=ship
|
|
80
|
+
EOF
|
|
81
|
+
|
|
82
|
+
SOCK=$(fm_backend_herdr_socket_path "$SESSION")
|
|
83
|
+
[ -n "$SOCK" ] || fail "could not resolve the isolated session's socket path"
|
|
84
|
+
|
|
85
|
+
# --- register the pane's agent idle, then drive idle->blocked ----------------
|
|
86
|
+
# report-agent is herdr's documented primitive for a non-built-in process to
|
|
87
|
+
# report its own agent state (docs/herdr-backend.md); routed through the lab
|
|
88
|
+
# helper's guarded `run` so it carries the trailing --session.
|
|
89
|
+
fm_herdr_lab_cli "$SESSION" pane report-agent "$PANE_ID" --source fm-evwait-test --agent claude --state idle >/dev/null 2>&1 \
|
|
90
|
+
|| fail "could not register the pane's agent as idle"
|
|
91
|
+
|
|
92
|
+
OUT="$SCRATCH/out"; RCF="$SCRATCH/rc"
|
|
93
|
+
: > "$OUT"; : > "$RCF"
|
|
94
|
+
# Bounded subscriber wait in the background; it must sit past the idle reconcile
|
|
95
|
+
# and return only when the pane transitions to blocked.
|
|
96
|
+
( fm_backend_herdr_wait_transition "$SESSION" 8 "$STATE" "$TARGET" > "$OUT"; echo $? > "$RCF" ) &
|
|
97
|
+
WPID=$!
|
|
98
|
+
sleep 0.5 # let it connect, subscribe, and reconcile the idle baseline
|
|
99
|
+
|
|
100
|
+
START=$(python3 -c 'import time; print(time.time())')
|
|
101
|
+
fm_herdr_lab_cli "$SESSION" pane report-agent "$PANE_ID" --source fm-evwait-test --agent claude --state blocked >/dev/null 2>&1 \
|
|
102
|
+
|| fail "could not drive the pane's agent to blocked"
|
|
103
|
+
wait "$WPID"
|
|
104
|
+
END=$(python3 -c 'import time; print(time.time())')
|
|
105
|
+
|
|
106
|
+
RC=$(cat "$RCF" 2>/dev/null || echo "")
|
|
107
|
+
REC=$(cat "$OUT" 2>/dev/null || echo "")
|
|
108
|
+
ELAPSED=$(python3 -c "print(f'{($END)-($START):.3f}')" 2>/dev/null || echo "?")
|
|
109
|
+
|
|
110
|
+
[ "$RC" = 0 ] || fail "wait_transition should return 0 on a real idle->blocked transition, got rc='$RC' rec='$REC'"
|
|
111
|
+
REC_PANE=$(fm_transition_pane_id "$REC")
|
|
112
|
+
REC_TO=$(fm_transition_to_status "$REC")
|
|
113
|
+
[ "$REC_PANE" = "$PANE_ID" ] || fail "the returned record's pane_id ('$REC_PANE') must match the driven pane ('$PANE_ID')"
|
|
114
|
+
[ "$REC_TO" = "blocked" ] || fail "the returned record's to_status must be 'blocked', got '$REC_TO'"
|
|
115
|
+
# Sub-second: comfortably under the ~240s stale-pane wedge timer this replaces.
|
|
116
|
+
UNDER_ONE=$(python3 -c "print('yes' if (($END)-($START)) < 1.0 else 'no')" 2>/dev/null || echo "no")
|
|
117
|
+
[ "$UNDER_ONE" = yes ] || echo "note: idle->blocked wake took ${ELAPSED}s (>1s; still far under the 240s wedge timer, not fatal)" >&2
|
|
118
|
+
pass "real herdr ($HERDR_VERSION): a driven idle->blocked transition returns the blocked record in ${ELAPSED}s (pane $PANE_ID)"
|
|
119
|
+
|
|
120
|
+
# --- the watcher's fast-path lands a stale record in the scratch wake queue ---
|
|
121
|
+
# Load the narrow production owner only after pointing it at scratch state, then
|
|
122
|
+
# override wake so the handler enqueues without exiting the test.
|
|
123
|
+
export FM_STATE_OVERRIDE="$STATE"
|
|
124
|
+
export FM_ROOT_OVERRIDE="$ROOT"
|
|
125
|
+
# shellcheck source=/dev/null
|
|
126
|
+
. "$ROOT/bin/fm-push-transition-lib.sh"
|
|
127
|
+
wake() { return 0; }
|
|
128
|
+
handle_push_transition herdr "$SESSION" "$REC"
|
|
129
|
+
[ -e "$STATE/.wake-queue" ] || fail "handle_push_transition did not create the wake queue"
|
|
130
|
+
grep -q 'stale' "$STATE/.wake-queue" || fail "the wake queue must carry a stale record: $(cat "$STATE/.wake-queue")"
|
|
131
|
+
grep -q "$TARGET" "$STATE/.wake-queue" || fail "the stale record must name the task window $TARGET"
|
|
132
|
+
grep -q 'herdr: agent blocked' "$STATE/.wake-queue" || fail "the stale payload must name the herdr-blocked cause"
|
|
133
|
+
pass "real herdr: the watcher fast-path enqueues a stale wake naming the task window from the live blocked transition"
|
|
134
|
+
|
|
135
|
+
cleanup_all
|
|
136
|
+
trap - EXIT
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
import importlib.util
|
|
3
|
+
import io
|
|
4
|
+
import socket
|
|
5
|
+
import time
|
|
6
|
+
import unittest
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from unittest import mock
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
READER_PATH = Path(__file__).parents[1] / "bin" / "backends" / "herdr-eventwait.py"
|
|
12
|
+
SPEC = importlib.util.spec_from_file_location("herdr_eventwait", READER_PATH)
|
|
13
|
+
READER = importlib.util.module_from_spec(SPEC)
|
|
14
|
+
SPEC.loader.exec_module(READER)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class FailingSocket:
|
|
18
|
+
def settimeout(self, _timeout):
|
|
19
|
+
pass
|
|
20
|
+
|
|
21
|
+
def recv(self, _size):
|
|
22
|
+
raise OSError("receive failed")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class ClosingStreamSocket:
|
|
26
|
+
def __init__(self):
|
|
27
|
+
self.chunks = [
|
|
28
|
+
b'{"result":{"type":"subscription_started"}}\n',
|
|
29
|
+
b"",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
def settimeout(self, _timeout):
|
|
33
|
+
pass
|
|
34
|
+
|
|
35
|
+
def connect(self, _path):
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
def sendall(self, _request):
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
def recv(self, _size):
|
|
42
|
+
return self.chunks.pop(0)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class RejectedSubscriptionSocket(ClosingStreamSocket):
|
|
46
|
+
def __init__(self):
|
|
47
|
+
self.chunks = [b'{"result":{"type":"not_started"}}\n']
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class EventWaitReadLineTest(unittest.TestCase):
|
|
51
|
+
def test_deadline_is_clean_timeout(self):
|
|
52
|
+
left, right = socket.socketpair()
|
|
53
|
+
self.addCleanup(left.close)
|
|
54
|
+
self.addCleanup(right.close)
|
|
55
|
+
|
|
56
|
+
line, buf, outcome = READER._read_line(left, b"", time.monotonic())
|
|
57
|
+
|
|
58
|
+
self.assertIsNone(line)
|
|
59
|
+
self.assertEqual(buf, b"")
|
|
60
|
+
self.assertEqual(outcome, "timeout")
|
|
61
|
+
|
|
62
|
+
def test_peer_closure_is_runtime_failure(self):
|
|
63
|
+
left, right = socket.socketpair()
|
|
64
|
+
self.addCleanup(left.close)
|
|
65
|
+
right.close()
|
|
66
|
+
|
|
67
|
+
line, buf, outcome = READER._read_line(
|
|
68
|
+
left, b"", time.monotonic() + 1
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
self.assertIsNone(line)
|
|
72
|
+
self.assertEqual(buf, b"")
|
|
73
|
+
self.assertEqual(outcome, "closed")
|
|
74
|
+
|
|
75
|
+
def test_receive_error_is_runtime_failure(self):
|
|
76
|
+
line, buf, outcome = READER._read_line(
|
|
77
|
+
FailingSocket(), b"", time.monotonic() + 1
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
self.assertIsNone(line)
|
|
81
|
+
self.assertEqual(buf, b"")
|
|
82
|
+
self.assertEqual(outcome, "error")
|
|
83
|
+
|
|
84
|
+
def test_main_reports_early_stream_closure(self):
|
|
85
|
+
stdout = io.StringIO()
|
|
86
|
+
with mock.patch.object(READER.socket, "socket", return_value=ClosingStreamSocket()):
|
|
87
|
+
with mock.patch.object(READER.sys, "stdout", stdout):
|
|
88
|
+
result = READER.main(["herdr-eventwait.py", "socket", "1", "pane"])
|
|
89
|
+
|
|
90
|
+
self.assertEqual(result, 4)
|
|
91
|
+
self.assertEqual(stdout.getvalue(), "@subscribed\n")
|
|
92
|
+
|
|
93
|
+
def test_main_does_not_signal_readiness_before_valid_ack(self):
|
|
94
|
+
stdout = io.StringIO()
|
|
95
|
+
with mock.patch.object(
|
|
96
|
+
READER.socket, "socket", return_value=RejectedSubscriptionSocket()
|
|
97
|
+
):
|
|
98
|
+
with mock.patch.object(READER.sys, "stdout", stdout):
|
|
99
|
+
result = READER.main(["herdr-eventwait.py", "socket", "1", "pane"])
|
|
100
|
+
|
|
101
|
+
self.assertEqual(result, 3)
|
|
102
|
+
self.assertEqual(stdout.getvalue(), "")
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
if __name__ == "__main__":
|
|
106
|
+
unittest.main()
|
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Real-Herdr regression for the projected-cleanup focus flash (upstream
|
|
3
|
+
# ogulcancelik/herdr#1621 family, live on 0.7.5 stable).
|
|
4
|
+
# Part A reproduces the OLD path: an explicit last-pane close that empties a
|
|
5
|
+
# non-focused workspace steals the focused workspace.
|
|
6
|
+
# Part B proves the mitigation: the focus-safe emptying-close plan
|
|
7
|
+
# (repositioning move plus pane-death removal) removes the doomed workspace
|
|
8
|
+
# with no focus change and no corrective tab focus at all.
|
|
9
|
+
# Part C covers the branch Part B structurally cannot reach - a doomed pane
|
|
10
|
+
# whose shell holds a persistent child, so the lone-idle-shell proof fails and
|
|
11
|
+
# the plan falls back to the plain explicit close - in the geometry where the
|
|
12
|
+
# closing workspace's right neighbour is not the anchor. It then checks the
|
|
13
|
+
# version floor that decides whether an unconfigured home is projected at all,
|
|
14
|
+
# against what Part A measured about this very release.
|
|
15
|
+
# On a future release whose explicit close preserves focus, Part A records
|
|
16
|
+
# that and Parts B and C keep outcome-only assertions, so no version is guessed.
|
|
17
|
+
# Every CLI operation is routed through one guarded named non-default lab, and
|
|
18
|
+
# lab teardown verifies that the default fleet session is byte-identical.
|
|
19
|
+
set -u
|
|
20
|
+
|
|
21
|
+
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
22
|
+
HERDR_LAB_HELPER=${HERDR_LAB_HELPER:-$ROOT/bin/fm-herdr-lab.sh}
|
|
23
|
+
|
|
24
|
+
fail() { printf 'not ok - %s\n' "$1" >&2; exit 1; }
|
|
25
|
+
pass() { printf 'ok - %s\n' "$1"; }
|
|
26
|
+
|
|
27
|
+
command -v herdr >/dev/null 2>&1 || { echo 'skip: herdr not found'; exit 0; }
|
|
28
|
+
command -v jq >/dev/null 2>&1 || { echo 'skip: jq not found'; exit 0; }
|
|
29
|
+
command -v python3 >/dev/null 2>&1 || { echo 'skip: python3 not found'; exit 0; }
|
|
30
|
+
[ -x "$HERDR_LAB_HELPER" ] || { echo "skip: Herdr lab helper not executable at $HERDR_LAB_HELPER"; exit 0; }
|
|
31
|
+
|
|
32
|
+
HERDR_ORIGINAL_PATH=$PATH
|
|
33
|
+
TMP_ROOT=$(mktemp -d "$(cd "${TMPDIR:-/tmp}" && pwd -P)/fm-herdr-focus-flash-e2e.XXXXXX")
|
|
34
|
+
FAKEBIN="$TMP_ROOT/fakebin"
|
|
35
|
+
mkdir -p "$FAKEBIN"
|
|
36
|
+
|
|
37
|
+
HERDR_LAB_SESSION=$("$HERDR_LAB_HELPER" name fm-herdr-focus-flash-regression-r1)
|
|
38
|
+
export HERDR_LAB_HELPER HERDR_LAB_SESSION HERDR_ORIGINAL_PATH
|
|
39
|
+
SAMPLER_PID=
|
|
40
|
+
SAMPLER_STOP=
|
|
41
|
+
cleanup() {
|
|
42
|
+
local status=$?
|
|
43
|
+
if [ -n "$SAMPLER_STOP" ]; then
|
|
44
|
+
: > "$SAMPLER_STOP"
|
|
45
|
+
fi
|
|
46
|
+
if [ -n "$SAMPLER_PID" ]; then
|
|
47
|
+
wait "$SAMPLER_PID" 2>/dev/null || true
|
|
48
|
+
fi
|
|
49
|
+
env PATH="$HERDR_ORIGINAL_PATH" "$HERDR_LAB_HELPER" teardown "$HERDR_LAB_SESSION" || status=1
|
|
50
|
+
rm -rf "$TMP_ROOT"
|
|
51
|
+
exit "$status"
|
|
52
|
+
}
|
|
53
|
+
trap cleanup EXIT
|
|
54
|
+
"$HERDR_LAB_HELPER" provision "$HERDR_LAB_SESSION"
|
|
55
|
+
|
|
56
|
+
# Keep the lab helper as the only CLI transport. Production adapter calls have
|
|
57
|
+
# already appended the exact session; this shim strips that pair, refuses every
|
|
58
|
+
# other caller-supplied session, and delegates the command to helper run.
|
|
59
|
+
cat > "$FAKEBIN/herdr" <<'SH'
|
|
60
|
+
#!/usr/bin/env bash
|
|
61
|
+
set -u
|
|
62
|
+
args=("$@")
|
|
63
|
+
last=$((${#args[@]} - 1))
|
|
64
|
+
flag=$((last - 1))
|
|
65
|
+
if [ "${#args[@]}" -ge 2 ] \
|
|
66
|
+
&& [ "${args[$flag]}" = --session ] \
|
|
67
|
+
&& [ "${args[$last]}" = "$HERDR_LAB_SESSION" ]; then
|
|
68
|
+
unset "args[$last]" "args[$flag]"
|
|
69
|
+
fi
|
|
70
|
+
set -- "${args[@]}"
|
|
71
|
+
for arg in "$@"; do
|
|
72
|
+
case "$arg" in --session|--session=*) exit 9 ;; esac
|
|
73
|
+
done
|
|
74
|
+
exec env PATH="$HERDR_ORIGINAL_PATH" "$HERDR_LAB_HELPER" run "$HERDR_LAB_SESSION" "$@"
|
|
75
|
+
SH
|
|
76
|
+
chmod +x "$FAKEBIN/herdr"
|
|
77
|
+
|
|
78
|
+
lab() { env PATH="$HERDR_ORIGINAL_PATH" "$HERDR_LAB_HELPER" run "$HERDR_LAB_SESSION" "$@"; }
|
|
79
|
+
mkws() { # <label> -> "<workspace_id> <tab_id> <pane_id>"
|
|
80
|
+
lab workspace create --cwd "$ROOT" --label "$1" --no-focus \
|
|
81
|
+
| jq -er '"\(.result.workspace.workspace_id) \(.result.tab.tab_id) \(.result.root_pane.pane_id)"'
|
|
82
|
+
}
|
|
83
|
+
focus_snapshot() {
|
|
84
|
+
local list workspace tab tabs
|
|
85
|
+
list=$(lab workspace list) || return 1
|
|
86
|
+
workspace=$(printf '%s' "$list" | jq -er '[.result.workspaces[] | select(.focused == true)] | select(length == 1) | .[0].workspace_id') || return 1
|
|
87
|
+
tab=$(printf '%s' "$list" | jq -er --arg workspace "$workspace" '[.result.workspaces[] | select(.workspace_id == $workspace)] | select(length == 1) | .[0].active_tab_id') || return 1
|
|
88
|
+
tabs=$(lab tab list --workspace "$workspace") || return 1
|
|
89
|
+
printf '%s' "$tabs" | jq -e --arg tab "$tab" '([.result.tabs[] | select(.focused == true)] | length) == 1 and ([.result.tabs[] | select(.focused == true)][0].tab_id == $tab)' >/dev/null || return 1
|
|
90
|
+
printf '%s\t%s' "$workspace" "$tab"
|
|
91
|
+
}
|
|
92
|
+
ws_order() { lab workspace list | jq -er '[.result.workspaces[].workspace_id] | join(",")'; }
|
|
93
|
+
wait_ws_gone() { # <workspace_id>
|
|
94
|
+
local i=0
|
|
95
|
+
while [ "$i" -lt 80 ]; do
|
|
96
|
+
lab workspace get "$1" >/dev/null 2>&1 || return 0
|
|
97
|
+
sleep 0.1
|
|
98
|
+
i=$((i + 1))
|
|
99
|
+
done
|
|
100
|
+
return 1
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
# --- Part A: the OLD path (plain explicit close) steals focus on 0.7.5 -----
|
|
104
|
+
# The spacer keeps the focused anchor away from the doomed workspace's right
|
|
105
|
+
# neighbor, where the 0.7.5 explicit close would land by coincidence.
|
|
106
|
+
read -r A_DOOMED_WS _ A_DOOMED_PANE <<<"$(mkws flash-a-doomed)" || fail 'could not create the Part A doomed workspace'
|
|
107
|
+
read -r _ _ _ <<<"$(mkws flash-a-spacer)" || fail 'could not create the Part A spacer workspace'
|
|
108
|
+
read -r A_ANCHOR_WS A_ANCHOR_TAB _ <<<"$(mkws flash-a-anchor)" || fail 'could not create the Part A anchor workspace'
|
|
109
|
+
read -r _ _ _ <<<"$(mkws flash-a-tail)" || fail 'could not create the Part A tail workspace'
|
|
110
|
+
lab tab focus "$A_ANCHOR_TAB" >/dev/null || fail 'could not focus the Part A anchor'
|
|
111
|
+
A_BEFORE=$(focus_snapshot) || fail 'could not capture the Part A pre-close focus'
|
|
112
|
+
[ "$A_BEFORE" = "$(printf '%s\t%s' "$A_ANCHOR_WS" "$A_ANCHOR_TAB")" ] \
|
|
113
|
+
|| fail 'Part A anchor focus does not match the intended workspace and tab'
|
|
114
|
+
lab pane close "$A_DOOMED_PANE" >/dev/null || fail 'Part A explicit close failed'
|
|
115
|
+
wait_ws_gone "$A_DOOMED_WS" || fail 'Part A doomed workspace survived the explicit close'
|
|
116
|
+
A_AFTER=$(focus_snapshot) || fail 'could not capture the Part A post-close focus'
|
|
117
|
+
STEAL_LIVE=0
|
|
118
|
+
if [ "$A_AFTER" != "$A_BEFORE" ]; then
|
|
119
|
+
STEAL_LIVE=1
|
|
120
|
+
pass "old path: the explicit last-pane close of a non-focused workspace stole focus ($A_BEFORE -> $A_AFTER)"
|
|
121
|
+
lab tab focus "$A_ANCHOR_TAB" >/dev/null || fail 'could not restore the Part A anchor focus'
|
|
122
|
+
else
|
|
123
|
+
pass 'old path note: this Herdr release preserves focus across the explicit close; continuing with outcome-only assertions'
|
|
124
|
+
fi
|
|
125
|
+
|
|
126
|
+
# --- Part B: the mitigation in the dangerous geometry ----------------------
|
|
127
|
+
# The doomed workspace sits BEFORE the focused anchor and the anchor is not
|
|
128
|
+
# last, the exact shape where an unrepositioned pane death also steals focus.
|
|
129
|
+
read -r B_DOOMED_WS _ B_DOOMED_PANE <<<"$(mkws flash-b-doomed)" || fail 'could not create the Part B doomed workspace'
|
|
130
|
+
read -r B_ANCHOR_WS B_ANCHOR_TAB _ <<<"$(mkws flash-b-anchor)" || fail 'could not create the Part B anchor workspace'
|
|
131
|
+
read -r _ _ _ <<<"$(mkws flash-b-tail)" || fail 'could not create the Part B tail workspace'
|
|
132
|
+
lab tab focus "$B_ANCHOR_TAB" >/dev/null || fail 'could not focus the Part B anchor'
|
|
133
|
+
B_BEFORE=$(focus_snapshot) || fail 'could not capture the Part B pre-close focus'
|
|
134
|
+
[ "$B_BEFORE" = "$(printf '%s\t%s' "$B_ANCHOR_WS" "$B_ANCHOR_TAB")" ] \
|
|
135
|
+
|| fail 'Part B anchor focus does not match the intended workspace and tab'
|
|
136
|
+
B_SURVIVOR_ORDER=$(ws_order | tr ',' '\n' | grep -v "^$B_DOOMED_WS\$" | paste -sd, -) \
|
|
137
|
+
|| fail 'could not capture the Part B survivor order'
|
|
138
|
+
|
|
139
|
+
CALL_LOG="$TMP_ROOT/call.log"
|
|
140
|
+
B_FOCUS_SAMPLES="$TMP_ROOT/focus.samples"
|
|
141
|
+
B_OPERATION_ACTIVE="$TMP_ROOT/operation.active"
|
|
142
|
+
B_SAMPLER_READY="$TMP_ROOT/sampler.ready"
|
|
143
|
+
SAMPLER_STOP="$TMP_ROOT/sampler.stop"
|
|
144
|
+
: > "$CALL_LOG"
|
|
145
|
+
: > "$B_FOCUS_SAMPLES"
|
|
146
|
+
(
|
|
147
|
+
: > "$B_SAMPLER_READY"
|
|
148
|
+
while [ ! -e "$SAMPLER_STOP" ]; do
|
|
149
|
+
if [ -e "$B_OPERATION_ACTIVE" ]; then
|
|
150
|
+
if B_SAMPLE=$(focus_snapshot); then
|
|
151
|
+
printf '%s\n' "$B_SAMPLE" >> "$B_FOCUS_SAMPLES"
|
|
152
|
+
else
|
|
153
|
+
printf '%s\n' UNREADABLE >> "$B_FOCUS_SAMPLES"
|
|
154
|
+
fi
|
|
155
|
+
fi
|
|
156
|
+
done
|
|
157
|
+
) &
|
|
158
|
+
SAMPLER_PID=$!
|
|
159
|
+
B_READY_ATTEMPT=0
|
|
160
|
+
while [ ! -e "$B_SAMPLER_READY" ] && [ "$B_READY_ATTEMPT" -lt 100 ]; do
|
|
161
|
+
sleep 0.01
|
|
162
|
+
B_READY_ATTEMPT=$((B_READY_ATTEMPT + 1))
|
|
163
|
+
done
|
|
164
|
+
[ -e "$B_SAMPLER_READY" ] || fail 'the Part B focus sampler did not start'
|
|
165
|
+
: > "$B_OPERATION_ACTIVE"
|
|
166
|
+
B_OUT=$(PATH="$FAKEBIN:$HERDR_ORIGINAL_PATH" FM_FLASH_CALL_LOG="$CALL_LOG" bash -c '
|
|
167
|
+
. "$1/bin/backends/herdr.sh"
|
|
168
|
+
fm_backend_herdr_cli() {
|
|
169
|
+
local session=$1
|
|
170
|
+
shift
|
|
171
|
+
printf "%s\n" "$*" >> "$FM_FLASH_CALL_LOG"
|
|
172
|
+
HERDR_SESSION="$session" herdr "$@" --session "$session"
|
|
173
|
+
}
|
|
174
|
+
fm_backend_herdr_projection_close_pane_focus_preserving "$2" "$3"
|
|
175
|
+
' _ "$ROOT" "$HERDR_LAB_SESSION" "$B_DOOMED_PANE" 2>&1)
|
|
176
|
+
B_STATUS=$?
|
|
177
|
+
rm -f "$B_OPERATION_ACTIVE"
|
|
178
|
+
: > "$SAMPLER_STOP"
|
|
179
|
+
wait "$SAMPLER_PID" 2>/dev/null || true
|
|
180
|
+
SAMPLER_PID=
|
|
181
|
+
[ "$B_STATUS" -eq 0 ] || fail "the production focus-preserving close failed (status $B_STATUS): $B_OUT"
|
|
182
|
+
[ -s "$B_FOCUS_SAMPLES" ] || fail 'the Part B sampler captured no focus sample during the production close'
|
|
183
|
+
B_WRONG_SAMPLE=$(grep -Fvx -- "$B_BEFORE" "$B_FOCUS_SAMPLES" | head -1)
|
|
184
|
+
if [ -n "$B_WRONG_SAMPLE" ]; then
|
|
185
|
+
fail "the mitigation exposed a wrong or unreadable in-operation focus sample ($B_BEFORE -> $B_WRONG_SAMPLE)"
|
|
186
|
+
fi
|
|
187
|
+
wait_ws_gone "$B_DOOMED_WS" || fail 'the mitigation left the doomed workspace behind'
|
|
188
|
+
if lab pane get "$B_DOOMED_PANE" >/dev/null 2>&1; then
|
|
189
|
+
fail 'the mitigation left the doomed pane behind'
|
|
190
|
+
fi
|
|
191
|
+
B_AFTER=$(focus_snapshot) || fail 'could not capture the Part B post-close focus'
|
|
192
|
+
[ "$B_AFTER" = "$B_BEFORE" ] \
|
|
193
|
+
|| fail "the mitigation changed the exact focused workspace or tab ($B_BEFORE -> $B_AFTER)"
|
|
194
|
+
[ "$(ws_order)" = "$B_SURVIVOR_ORDER" ] \
|
|
195
|
+
|| fail "the mitigation left a lasting workspace order change ($B_SURVIVOR_ORDER -> $(ws_order))"
|
|
196
|
+
grep -q '^pane process-info' "$CALL_LOG" || fail 'the idle-shell proof never ran'
|
|
197
|
+
pass 'mitigation: every in-operation sample preserved exact focus while the doomed workspace was removed'
|
|
198
|
+
|
|
199
|
+
if [ "$STEAL_LIVE" = 1 ]; then
|
|
200
|
+
grep -q '^tab focus' "$CALL_LOG" \
|
|
201
|
+
&& fail 'the corrective tab focus fired, so a wrong-focus interval existed on the defective release'
|
|
202
|
+
grep -q '^pane close' "$CALL_LOG" \
|
|
203
|
+
&& fail 'the focus-unsafe explicit close was used on the defective release'
|
|
204
|
+
pass 'mitigation: no explicit close and no corrective focus were needed on the defective release'
|
|
205
|
+
fi
|
|
206
|
+
|
|
207
|
+
# --- Part C: the plain-close FALLBACK, the case Part B cannot reach ---------
|
|
208
|
+
# Part B always hands the adapter a freshly created workspace whose pane is a
|
|
209
|
+
# bare idle shell, so its emptying-close plan always takes the focus-preserving
|
|
210
|
+
# pane-death route. The reported defect lives on the other branch: a doomed pane
|
|
211
|
+
# whose shell holds a PERSISTENT child (a gitstatusd, a zsh-async worker,
|
|
212
|
+
# direnv, or anything a crewmate backgrounded) fails the lone-idle-shell proof
|
|
213
|
+
# permanently, and the plan falls back to the plain explicit close.
|
|
214
|
+
# The geometry puts the doomed workspace AFTER the anchor so the plan performs
|
|
215
|
+
# no repositioning at all, and puts a spacer immediately to its right so the
|
|
216
|
+
# closing workspace's right neighbour - where a defective release lands focus -
|
|
217
|
+
# is not the anchor. That is the exact shape the reporter saw.
|
|
218
|
+
read -r C_ANCHOR_WS C_ANCHOR_TAB _ <<<"$(mkws flash-c-anchor)" || fail 'could not create the Part C anchor workspace'
|
|
219
|
+
read -r C_DOOMED_WS _ C_DOOMED_PANE <<<"$(mkws flash-c-doomed)" || fail 'could not create the Part C doomed workspace'
|
|
220
|
+
read -r C_SPACER_WS _ _ <<<"$(mkws flash-c-spacer)" || fail 'could not create the Part C spacer workspace'
|
|
221
|
+
read -r _ _ _ <<<"$(mkws flash-c-tail)" || fail 'could not create the Part C tail workspace'
|
|
222
|
+
lab tab focus "$C_ANCHOR_TAB" >/dev/null || fail 'could not focus the Part C anchor'
|
|
223
|
+
C_BEFORE=$(focus_snapshot) || fail 'could not capture the Part C pre-close focus'
|
|
224
|
+
[ "$C_BEFORE" = "$(printf '%s\t%s' "$C_ANCHOR_WS" "$C_ANCHOR_TAB")" ] \
|
|
225
|
+
|| fail 'Part C anchor focus does not match the intended workspace and tab'
|
|
226
|
+
|
|
227
|
+
# Assert the geometry itself, so the case can never pass vacuously on a layout
|
|
228
|
+
# where the plain close would land on the anchor by coincidence.
|
|
229
|
+
C_ORDER=$(ws_order) || fail 'could not read the Part C workspace order'
|
|
230
|
+
C_RIGHT_NEIGHBOUR=$(printf '%s' "$C_ORDER" | tr ',' '\n' | grep -A1 -Fx "$C_DOOMED_WS" | tail -1)
|
|
231
|
+
[ "$C_RIGHT_NEIGHBOUR" = "$C_SPACER_WS" ] \
|
|
232
|
+
|| fail "Part C needs the spacer immediately right of the doomed workspace, got '$C_RIGHT_NEIGHBOUR'"
|
|
233
|
+
[ "$C_RIGHT_NEIGHBOUR" != "$C_ANCHOR_WS" ] \
|
|
234
|
+
|| fail 'Part C geometry is vacuous: the right neighbour of the doomed workspace is the anchor'
|
|
235
|
+
C_SURVIVOR_ORDER=$(printf '%s' "$C_ORDER" | tr ',' '\n' | grep -v "^$C_DOOMED_WS\$" | paste -sd, -) \
|
|
236
|
+
|| fail 'could not capture the Part C survivor order'
|
|
237
|
+
|
|
238
|
+
# One persistent background child of the pane's shell, started outside any
|
|
239
|
+
# worktree so nothing reaps it, is enough to fail the proof on every sample.
|
|
240
|
+
lab pane send-text "$C_DOOMED_PANE" 'cd / && sleep 3000 &' >/dev/null \
|
|
241
|
+
|| fail 'could not send the Part C persistent-child command'
|
|
242
|
+
lab pane send-keys "$C_DOOMED_PANE" enter >/dev/null \
|
|
243
|
+
|| fail 'could not submit the Part C persistent-child command'
|
|
244
|
+
C_SHELL_PID=
|
|
245
|
+
C_CHILD_ATTEMPT=0
|
|
246
|
+
C_CHILD_STABLE=0
|
|
247
|
+
while [ "$C_CHILD_ATTEMPT" -lt 100 ]; do
|
|
248
|
+
C_SHELL_PID=$(lab pane process-info --pane "$C_DOOMED_PANE" 2>/dev/null \
|
|
249
|
+
| jq -r '.result.process_info.shell_pid // empty' 2>/dev/null) || C_SHELL_PID=
|
|
250
|
+
if [ -n "$C_SHELL_PID" ] && ps -axo ppid=,comm= | awk -v parent="$C_SHELL_PID" '
|
|
251
|
+
$1 == parent {
|
|
252
|
+
command = $2
|
|
253
|
+
sub(/^.*\//, "", command)
|
|
254
|
+
if (command == "sleep") found = 1
|
|
255
|
+
}
|
|
256
|
+
END { exit(found ? 0 : 1) }
|
|
257
|
+
'; then
|
|
258
|
+
C_CHILD_STABLE=$((C_CHILD_STABLE + 1))
|
|
259
|
+
[ "$C_CHILD_STABLE" -ge 2 ] && break
|
|
260
|
+
else
|
|
261
|
+
C_CHILD_STABLE=0
|
|
262
|
+
C_SHELL_PID=
|
|
263
|
+
fi
|
|
264
|
+
sleep 0.1
|
|
265
|
+
C_CHILD_ATTEMPT=$((C_CHILD_ATTEMPT + 1))
|
|
266
|
+
done
|
|
267
|
+
[ "$C_CHILD_STABLE" -ge 2 ] || fail 'the Part C doomed pane never acquired a stable persistent sleep child process'
|
|
268
|
+
|
|
269
|
+
C_CALL_LOG="$TMP_ROOT/call-c.log"
|
|
270
|
+
C_FOCUS_SAMPLES="$TMP_ROOT/focus-c.samples"
|
|
271
|
+
C_OPERATION_ACTIVE="$TMP_ROOT/operation-c.active"
|
|
272
|
+
C_SAMPLER_READY="$TMP_ROOT/sampler-c.ready"
|
|
273
|
+
SAMPLER_STOP="$TMP_ROOT/sampler-c.stop"
|
|
274
|
+
: > "$C_CALL_LOG"
|
|
275
|
+
: > "$C_FOCUS_SAMPLES"
|
|
276
|
+
(
|
|
277
|
+
: > "$C_SAMPLER_READY"
|
|
278
|
+
while [ ! -e "$SAMPLER_STOP" ]; do
|
|
279
|
+
if [ -e "$C_OPERATION_ACTIVE" ]; then
|
|
280
|
+
if C_SAMPLE=$(focus_snapshot); then
|
|
281
|
+
printf '%s\n' "$C_SAMPLE" >> "$C_FOCUS_SAMPLES"
|
|
282
|
+
else
|
|
283
|
+
printf '%s\n' UNREADABLE >> "$C_FOCUS_SAMPLES"
|
|
284
|
+
fi
|
|
285
|
+
fi
|
|
286
|
+
done
|
|
287
|
+
) &
|
|
288
|
+
SAMPLER_PID=$!
|
|
289
|
+
C_READY_ATTEMPT=0
|
|
290
|
+
while [ ! -e "$C_SAMPLER_READY" ] && [ "$C_READY_ATTEMPT" -lt 100 ]; do
|
|
291
|
+
sleep 0.01
|
|
292
|
+
C_READY_ATTEMPT=$((C_READY_ATTEMPT + 1))
|
|
293
|
+
done
|
|
294
|
+
[ -e "$C_SAMPLER_READY" ] || fail 'the Part C focus sampler did not start'
|
|
295
|
+
: > "$C_OPERATION_ACTIVE"
|
|
296
|
+
# A short proof budget keeps the exhausted-proof path fast; the count below is
|
|
297
|
+
# what proves the proof was exhausted rather than skipped.
|
|
298
|
+
C_PROOF_POLLS=3
|
|
299
|
+
C_OUT=$(PATH="$FAKEBIN:$HERDR_ORIGINAL_PATH" FM_FLASH_CALL_LOG="$C_CALL_LOG" \
|
|
300
|
+
FM_BACKEND_HERDR_IDLE_SHELL_PROOF_POLLS="$C_PROOF_POLLS" bash -c '
|
|
301
|
+
. "$1/bin/backends/herdr.sh"
|
|
302
|
+
fm_backend_herdr_cli() {
|
|
303
|
+
local session=$1
|
|
304
|
+
shift
|
|
305
|
+
printf "%s\n" "$*" >> "$FM_FLASH_CALL_LOG"
|
|
306
|
+
HERDR_SESSION="$session" herdr "$@" --session "$session"
|
|
307
|
+
}
|
|
308
|
+
fm_backend_herdr_projection_close_pane_focus_preserving "$2" "$3"
|
|
309
|
+
' _ "$ROOT" "$HERDR_LAB_SESSION" "$C_DOOMED_PANE" 2>&1)
|
|
310
|
+
C_STATUS=$?
|
|
311
|
+
rm -f "$C_OPERATION_ACTIVE"
|
|
312
|
+
: > "$SAMPLER_STOP"
|
|
313
|
+
wait "$SAMPLER_PID" 2>/dev/null || true
|
|
314
|
+
SAMPLER_PID=
|
|
315
|
+
[ "$C_STATUS" -eq 0 ] || fail "the production focus-preserving close failed (status $C_STATUS): $C_OUT"
|
|
316
|
+
wait_ws_gone "$C_DOOMED_WS" || fail 'the fallback close left the doomed workspace behind'
|
|
317
|
+
if lab pane get "$C_DOOMED_PANE" >/dev/null 2>&1; then
|
|
318
|
+
fail 'the fallback close left the doomed pane behind'
|
|
319
|
+
fi
|
|
320
|
+
[ "$(ws_order)" = "$C_SURVIVOR_ORDER" ] \
|
|
321
|
+
|| fail "the fallback close left a lasting workspace order change ($C_SURVIVOR_ORDER -> $(ws_order))"
|
|
322
|
+
|
|
323
|
+
# Prove the FALLBACK is what ran, not the pane-death route Part B covers: the
|
|
324
|
+
# idle-shell proof must have been attempted and exhausted, and the explicit
|
|
325
|
+
# close must have been issued.
|
|
326
|
+
C_PROOF_CALLS=$(grep -c '^pane process-info' "$C_CALL_LOG" || true)
|
|
327
|
+
[ "$C_PROOF_CALLS" -eq "$C_PROOF_POLLS" ] \
|
|
328
|
+
|| fail "Part C did not exhaust the idle-shell proof ($C_PROOF_CALLS of $C_PROOF_POLLS samples); the persistent child did not block it"
|
|
329
|
+
grep -q '^pane close' "$C_CALL_LOG" \
|
|
330
|
+
|| fail 'Part C never reached the plain explicit close, so the fallback branch was not exercised'
|
|
331
|
+
pass 'fallback: a doomed pane holding a persistent child exhausts the proof and takes the plain explicit close'
|
|
332
|
+
|
|
333
|
+
C_AFTER=$(focus_snapshot) || fail 'could not capture the Part C post-close focus'
|
|
334
|
+
[ "$C_AFTER" = "$C_BEFORE" ] \
|
|
335
|
+
|| fail "the fallback close left focus off the anchor ($C_BEFORE -> $C_AFTER)"
|
|
336
|
+
C_WRONG=$(grep -Fvxc -- "$C_BEFORE" "$C_FOCUS_SAMPLES" || true)
|
|
337
|
+
if [ "$STEAL_LIVE" = 1 ]; then
|
|
338
|
+
# A defective release cannot make this path focus-safe, which is precisely why
|
|
339
|
+
# default-on projection is floored above it. The wrong-focus window is
|
|
340
|
+
# explicitly accepted here, but only as a BOUNDED one: the restore backstop
|
|
341
|
+
# must have put the anchor back exactly, and the whole exposure must end with
|
|
342
|
+
# the operation rather than parking the captain somewhere else.
|
|
343
|
+
[ "$C_WRONG" -ge 1 ] \
|
|
344
|
+
|| fail 'Part C reached the fallback on a defective release but observed no wrong-focus sample at all, so the sampler proved nothing'
|
|
345
|
+
pass "fallback on a defective release: a bounded wrong-focus window of $C_WRONG samples was fully restored to the anchor"
|
|
346
|
+
else
|
|
347
|
+
[ "$C_WRONG" -eq 0 ] \
|
|
348
|
+
|| fail "a focus-preserving release exposed $C_WRONG wrong-focus samples on the fallback path"
|
|
349
|
+
pass 'fallback on a focus-preserving release: the plain explicit close preserved exact focus throughout'
|
|
350
|
+
fi
|
|
351
|
+
|
|
352
|
+
# The live guard on the version floor itself: Part A measured whether THIS
|
|
353
|
+
# release steals focus. Every above-floor release must preserve focus, while a
|
|
354
|
+
# below-floor release may conservatively include the known post-fix protocol-18
|
|
355
|
+
# preview without weakening the stated 0.8.0 policy floor.
|
|
356
|
+
STATUS=$(lab status --json) || fail 'could not read final named-lab version evidence'
|
|
357
|
+
LIVE_VERSION=$(printf '%s' "$STATUS" | jq -r '.client.version')
|
|
358
|
+
LIVE_PROTOCOL=$(printf '%s' "$STATUS" | jq -r '.client.protocol')
|
|
359
|
+
FLOOR_VERDICT=$(bash -c '
|
|
360
|
+
. "$0/bin/backends/herdr.sh"
|
|
361
|
+
status=0
|
|
362
|
+
fm_backend_herdr_release_floor_verdict "$1" "$2" || status=$?
|
|
363
|
+
printf "%s\n" "$status"
|
|
364
|
+
' "$ROOT" "$LIVE_PROTOCOL" "$LIVE_VERSION")
|
|
365
|
+
case "$FLOOR_VERDICT" in
|
|
366
|
+
0)
|
|
367
|
+
[ "$STEAL_LIVE" = 0 ] \
|
|
368
|
+
|| fail "herdr $LIVE_VERSION (protocol $LIVE_PROTOCOL) is at or above the floor but steals focus on the explicit close"
|
|
369
|
+
pass "version floor: herdr $LIVE_VERSION protocol $LIVE_PROTOCOL is at or above the floor and preserves focus"
|
|
370
|
+
;;
|
|
371
|
+
1)
|
|
372
|
+
pass "version floor: herdr $LIVE_VERSION protocol $LIVE_PROTOCOL remains conservatively below the floor with steal_live=$STEAL_LIVE"
|
|
373
|
+
;;
|
|
374
|
+
*) fail "herdr $LIVE_VERSION (protocol $LIVE_PROTOCOL) could not be classified against the presentation floor" ;;
|
|
375
|
+
esac
|
|
376
|
+
|
|
377
|
+
# The end-user gate: an unconfigured home must project only at or above the
|
|
378
|
+
# floor, and an explicit opt-in must survive either way.
|
|
379
|
+
FLOOR_CONFIG="$TMP_ROOT/floor-config"
|
|
380
|
+
FLOOR_STATE="$TMP_ROOT/floor-state"
|
|
381
|
+
mkdir -p "$FLOOR_CONFIG" "$FLOOR_STATE"
|
|
382
|
+
gate_verdict() { # <config-dir> -> on|off, warnings on stderr
|
|
383
|
+
PATH="$FAKEBIN:$HERDR_ORIGINAL_PATH" HERDR_SESSION="$HERDR_LAB_SESSION" bash -c '
|
|
384
|
+
. "$0/bin/backends/herdr.sh"
|
|
385
|
+
if fm_backend_herdr_presentation_enabled "$1" "$2"; then printf "on\n"; else printf "off\n"; fi
|
|
386
|
+
' "$ROOT" "$1" "$FLOOR_STATE"
|
|
387
|
+
}
|
|
388
|
+
GATE_ERR="$TMP_ROOT/gate.err"
|
|
389
|
+
GATE_DEFAULT=$(gate_verdict "$FLOOR_CONFIG" 2>"$GATE_ERR")
|
|
390
|
+
printf 'on\n' > "$FLOOR_CONFIG/herdr-presentation-spaces"
|
|
391
|
+
GATE_OPT_IN=$(gate_verdict "$FLOOR_CONFIG" 2>/dev/null)
|
|
392
|
+
[ "$GATE_OPT_IN" = on ] \
|
|
393
|
+
|| fail "an explicit opt-in must stay on for herdr $LIVE_VERSION, got '$GATE_OPT_IN'"
|
|
394
|
+
if [ "$FLOOR_VERDICT" = 1 ]; then
|
|
395
|
+
[ "$GATE_DEFAULT" = off ] \
|
|
396
|
+
|| fail "an unconfigured home must not be projected on below-floor herdr $LIVE_VERSION, got '$GATE_DEFAULT'"
|
|
397
|
+
grep -q "$LIVE_VERSION" "$GATE_ERR" \
|
|
398
|
+
|| fail "the below-floor fallback must name herdr $LIVE_VERSION: $(cat "$GATE_ERR")"
|
|
399
|
+
pass "version floor: an unconfigured home falls back flat on herdr $LIVE_VERSION and the explicit opt-in still projects"
|
|
400
|
+
else
|
|
401
|
+
[ "$GATE_DEFAULT" = on ] \
|
|
402
|
+
|| fail "an unconfigured home must stay projected on herdr $LIVE_VERSION, got '$GATE_DEFAULT'"
|
|
403
|
+
[ ! -s "$GATE_ERR" ] \
|
|
404
|
+
|| fail "a supported release must warn about nothing: $(cat "$GATE_ERR")"
|
|
405
|
+
pass "version floor: an unconfigured home stays projected on herdr $LIVE_VERSION and the explicit opt-in agrees"
|
|
406
|
+
fi
|
|
407
|
+
|
|
408
|
+
printf 'evidence: herdr=%s protocol=%s steal_live=%s floor_verdict=%s default-session-tripwire=armed\n' \
|
|
409
|
+
"$LIVE_VERSION" "$LIVE_PROTOCOL" "$STEAL_LIVE" "$FLOOR_VERDICT"
|