@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,355 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# tests/fm-backend-herdr-smoke.test.sh - real herdr smoke test for the herdr
|
|
3
|
+
# session-provider adapter (bin/backends/herdr.sh), P2 of
|
|
4
|
+
# data/fm-backend-design-d7 (herdr-addendum.md), extended for the P3
|
|
5
|
+
# workspace-per-home pass (AGENTS.md task herdr-sm-spaces-k4). Mirrors
|
|
6
|
+
# tests/fm-backend-tmux-smoke.test.sh's structure: every other suite fakes the
|
|
7
|
+
# CLI, this one talks to a REAL herdr server - but ALWAYS on a private, named,
|
|
8
|
+
# throwaway HERDR_SESSION (never the default session), so it never touches a
|
|
9
|
+
# captain's real herdr usage. Skips cleanly when herdr (or jq) is not
|
|
10
|
+
# installed, so CI/dev machines without herdr are unaffected.
|
|
11
|
+
#
|
|
12
|
+
# Safety (2026-07-02 incident, see tests/herdr-test-safety.sh): cleanup uses
|
|
13
|
+
# ONLY herdr_safe_stop_and_delete, never a bare/ambient `herdr server stop` -
|
|
14
|
+
# that command killed the captain's live default herdr server twice in
|
|
15
|
+
# production because HERDR_SESSION-based targeting (env var OR inline prefix)
|
|
16
|
+
# is not reliably honored once another herdr server is already running.
|
|
17
|
+
set -u
|
|
18
|
+
|
|
19
|
+
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
20
|
+
|
|
21
|
+
fail() { printf 'not ok - %s\n' "$1" >&2; cleanup_all; exit 1; }
|
|
22
|
+
pass() { printf 'ok - %s\n' "$1"; }
|
|
23
|
+
|
|
24
|
+
command -v herdr >/dev/null 2>&1 || { echo "skip: herdr not found"; exit 0; }
|
|
25
|
+
command -v jq >/dev/null 2>&1 || { echo "skip: jq not found (required by the herdr adapter)"; exit 0; }
|
|
26
|
+
|
|
27
|
+
# shellcheck source=tests/herdr-test-safety.sh
|
|
28
|
+
. "$ROOT/tests/herdr-test-safety.sh"
|
|
29
|
+
|
|
30
|
+
# This suite runs against its own isolated lab session, so a Herdr pane
|
|
31
|
+
# inherited from the terminal it was launched in must not follow spawn into it
|
|
32
|
+
# as a cross-session parent identity (tests/herdr-test-safety.sh).
|
|
33
|
+
herdr_forget_inherited_pane
|
|
34
|
+
|
|
35
|
+
SESSION="fm-lab-backend-smoke-$$"
|
|
36
|
+
export HERDR_SESSION="$SESSION"
|
|
37
|
+
SM_SCRATCH=
|
|
38
|
+
cleanup_all() {
|
|
39
|
+
[ -n "$SM_SCRATCH" ] && rm -rf "$SM_SCRATCH"
|
|
40
|
+
herdr_safe_stop_and_delete "$SESSION"
|
|
41
|
+
}
|
|
42
|
+
trap cleanup_all EXIT
|
|
43
|
+
fm_herdr_lab_prepare "$SESSION" || fail "could not prepare isolated Herdr lab session"
|
|
44
|
+
|
|
45
|
+
# shellcheck source=/dev/null
|
|
46
|
+
. "$ROOT/bin/fm-backend.sh"
|
|
47
|
+
fm_backend_source herdr || fail "fm_backend_source herdr failed"
|
|
48
|
+
|
|
49
|
+
# --- version gate + container ensure -----------------------------------------
|
|
50
|
+
|
|
51
|
+
fm_backend_herdr_version_check || fail "version_check failed against the real installed herdr"
|
|
52
|
+
pass "real herdr: version_check accepts the installed binary's protocol"
|
|
53
|
+
|
|
54
|
+
# fm_backend_herdr_container_ensure now echoes
|
|
55
|
+
# "<session>:<workspace_id>\t<seeded_default_tab_id>" (the second field empty
|
|
56
|
+
# when the call ADOPTED a pre-existing workspace rather than creating a fresh
|
|
57
|
+
# one - docs/herdr-backend.md "Default-tab prune"). Split on the guaranteed
|
|
58
|
+
# single tab character; only fm_backend_herdr_create_task is ever allowed to
|
|
59
|
+
# act on the seeded tab id, and only for the container that just created it.
|
|
60
|
+
CONTAINER_RAW=$(fm_backend_herdr_container_ensure /tmp) || fail "container_ensure failed"
|
|
61
|
+
CONTAINER=${CONTAINER_RAW%%$'\t'*}
|
|
62
|
+
SEEDED_TAB_ID=${CONTAINER_RAW#*$'\t'}
|
|
63
|
+
case "$CONTAINER" in
|
|
64
|
+
"$SESSION":w*) : ;;
|
|
65
|
+
*) fail "container_ensure returned an unexpected shape: $CONTAINER" ;;
|
|
66
|
+
esac
|
|
67
|
+
[ -n "$SEEDED_TAB_ID" ] || fail "the first container_ensure in a brand-new isolated session must CREATE the workspace and report its seeded default tab id"
|
|
68
|
+
pass "real herdr: container_ensure starts the isolated session's server, creates the firstmate workspace ($CONTAINER), and reports its seeded default tab id ($SEEDED_TAB_ID)"
|
|
69
|
+
|
|
70
|
+
# A second container_ensure must reuse (ADOPT) the same workspace (idempotent)
|
|
71
|
+
# and report an EMPTY seeded tab id - the created-vs-adopted gate that fixes
|
|
72
|
+
# the 2026-07-02 self-kill incident (docs/herdr-backend.md "Default-tab
|
|
73
|
+
# prune"): only the call that actually just created a workspace may identify
|
|
74
|
+
# a tab as prunable.
|
|
75
|
+
CONTAINER2_RAW=$(fm_backend_herdr_container_ensure /tmp) || fail "second container_ensure failed"
|
|
76
|
+
CONTAINER2=${CONTAINER2_RAW%%$'\t'*}
|
|
77
|
+
SEEDED_TAB_ID2=${CONTAINER2_RAW#*$'\t'}
|
|
78
|
+
[ "$CONTAINER2" = "$CONTAINER" ] || fail "container_ensure is not idempotent: '$CONTAINER' vs '$CONTAINER2'"
|
|
79
|
+
[ -z "$SEEDED_TAB_ID2" ] || fail "an ADOPTED (reused) workspace must report an EMPTY seeded default tab id, got '$SEEDED_TAB_ID2'"
|
|
80
|
+
pass "real herdr: container_ensure is idempotent (reuses/adopts the existing firstmate workspace, reports no seeded default tab on adoption)"
|
|
81
|
+
|
|
82
|
+
# --- create_task + duplicate refusal + default-tab prune ---------------------
|
|
83
|
+
|
|
84
|
+
LABEL="fm-smoke1"
|
|
85
|
+
TASK_IDS=$(fm_backend_herdr_create_task "$CONTAINER" "$LABEL" /tmp "$SEEDED_TAB_ID") || fail "create_task failed"
|
|
86
|
+
read -r TAB_ID PANE_ID <<EOF
|
|
87
|
+
$TASK_IDS
|
|
88
|
+
EOF
|
|
89
|
+
if [ -z "$TAB_ID" ] || [ -z "$PANE_ID" ]; then
|
|
90
|
+
fail "create_task did not return tab/pane ids"
|
|
91
|
+
fi
|
|
92
|
+
TARGET="$SESSION:$PANE_ID"
|
|
93
|
+
|
|
94
|
+
# The happy path: a fresh workspace's seeded default tab (label "1") must be
|
|
95
|
+
# pruned once the first real task tab is created alongside it, leaving
|
|
96
|
+
# exactly one clean fm-<id> task tab.
|
|
97
|
+
POST_CREATE_TABS=$(herdr tab list --workspace "${CONTAINER#*:}" --session "$SESSION" 2>&1)
|
|
98
|
+
POST_CREATE_COUNT=$(printf '%s' "$POST_CREATE_TABS" | jq -r '.result.tabs? // [] | length')
|
|
99
|
+
[ "$POST_CREATE_COUNT" = 1 ] || fail "expected exactly 1 tab (the seeded default pruned) after the first real task tab, got $POST_CREATE_COUNT: $POST_CREATE_TABS"
|
|
100
|
+
printf '%s' "$POST_CREATE_TABS" | jq -e --arg t "$SEEDED_TAB_ID" '.result.tabs[] | select(.tab_id == $t)' >/dev/null 2>&1 \
|
|
101
|
+
&& fail "the seeded default tab ($SEEDED_TAB_ID) should have been pruned but is still present: $POST_CREATE_TABS"
|
|
102
|
+
pass "real herdr: create_task prunes the freshly-created workspace's seeded default tab, leaving exactly one clean fm-<id> task tab"
|
|
103
|
+
|
|
104
|
+
# NOTE: create_task no longer refuses EVERY same-labeled duplicate
|
|
105
|
+
# unconditionally - a same-labeled tab whose pane hosts no registered agent is
|
|
106
|
+
# now a close-and-replace candidate (the restored-layout husk fix below), so
|
|
107
|
+
# testing "$LABEL"/$PANE_ID again here would actually succeed and silently
|
|
108
|
+
# replace this suite's own primary task pane, which the rest of this file
|
|
109
|
+
# still depends on ($TARGET, the restart-stability check, send/capture/kill).
|
|
110
|
+
# The duplicate-refusal and husk-replacement behaviors are covered next,
|
|
111
|
+
# each against its own independent throwaway tab.
|
|
112
|
+
|
|
113
|
+
# --- restored-layout husk close-and-replace, against the REAL binary --------
|
|
114
|
+
# (docs/herdr-backend.md "Known gaps" / "ID stability across a server
|
|
115
|
+
# restart"). herdr persists and restores its whole session layout across a
|
|
116
|
+
# server restart, and a restored fm-<id> task tab comes back a HUSK: a dead
|
|
117
|
+
# pane, or (verified above and empirically in "ID stability") a plain
|
|
118
|
+
# agent-less shell. Both throwaway tabs below are independent of $TAB_ID/
|
|
119
|
+
# $PANE_ID/$TARGET (this suite's primary task, which the rest of the file
|
|
120
|
+
# still depends on) so neither scenario disturbs it.
|
|
121
|
+
|
|
122
|
+
# 1. A genuinely LIVE duplicate (a real registered agent, via herdr's own
|
|
123
|
+
# `pane report-agent`) must still refuse exactly as before.
|
|
124
|
+
LIVE_DUP_LABEL="fm-smoke-livedup"
|
|
125
|
+
LIVE_DUP_IDS=$(fm_backend_herdr_create_task "$CONTAINER" "$LIVE_DUP_LABEL" /tmp) || fail "could not create the live-duplicate scenario's tab"
|
|
126
|
+
read -r LIVE_DUP_TAB_ID LIVE_DUP_PANE_ID <<EOF
|
|
127
|
+
$LIVE_DUP_IDS
|
|
128
|
+
EOF
|
|
129
|
+
if [ -z "$LIVE_DUP_TAB_ID" ] || [ -z "$LIVE_DUP_PANE_ID" ]; then
|
|
130
|
+
fail "live-duplicate scenario tab creation did not return ids"
|
|
131
|
+
fi
|
|
132
|
+
herdr pane report-agent "$LIVE_DUP_PANE_ID" --source fm-smoke-test --agent fm-smoke-live-agent --state idle --session "$SESSION" >/dev/null 2>&1 \
|
|
133
|
+
|| fail "could not register a live agent on the live-duplicate scenario's pane"
|
|
134
|
+
if fm_backend_herdr_create_task "$CONTAINER" "$LIVE_DUP_LABEL" /tmp >/dev/null 2>&1; then
|
|
135
|
+
fail "REGRESSION: create_task should refuse a duplicate label whose pane hosts a genuinely live registered agent (idle counts as live)"
|
|
136
|
+
fi
|
|
137
|
+
herdr pane get "$LIVE_DUP_PANE_ID" --session "$SESSION" >/dev/null 2>&1 \
|
|
138
|
+
|| fail "REGRESSION: the live-duplicate scenario's pane should have survived the refused create_task call untouched"
|
|
139
|
+
pass "real herdr: create_task refuses a same-labeled tab whose pane hosts a genuinely live registered agent (unchanged behavior)"
|
|
140
|
+
fm_backend_herdr_kill "$SESSION:$LIVE_DUP_PANE_ID"
|
|
141
|
+
|
|
142
|
+
# 2. A husk (no registered agent at all - the restored-plain-shell shape)
|
|
143
|
+
# must be CLOSED AND REPLACED instead of refused.
|
|
144
|
+
HUSK_LABEL="fm-smoke-husk1"
|
|
145
|
+
HUSK_IDS=$(fm_backend_herdr_create_task "$CONTAINER" "$HUSK_LABEL" /tmp) || fail "could not create the husk-simulation tab"
|
|
146
|
+
read -r HUSK_TAB_ID HUSK_PANE_ID <<EOF
|
|
147
|
+
$HUSK_IDS
|
|
148
|
+
EOF
|
|
149
|
+
if [ -z "$HUSK_TAB_ID" ] || [ -z "$HUSK_PANE_ID" ]; then
|
|
150
|
+
fail "husk-simulation tab creation did not return ids"
|
|
151
|
+
fi
|
|
152
|
+
herdr agent get "$HUSK_PANE_ID" --session "$SESSION" >/dev/null 2>&1 \
|
|
153
|
+
&& fail "husk-simulation setup is wrong: this pane should have NO registered agent yet"
|
|
154
|
+
REPLACED_IDS=$(fm_backend_herdr_create_task "$CONTAINER" "$HUSK_LABEL" /tmp) \
|
|
155
|
+
|| fail "REGRESSION: create_task should close-and-replace a same-labeled tab whose pane hosts no registered agent, not refuse it"
|
|
156
|
+
read -r NEW_HUSK_TAB_ID NEW_HUSK_PANE_ID <<EOF
|
|
157
|
+
$REPLACED_IDS
|
|
158
|
+
EOF
|
|
159
|
+
if [ -z "$NEW_HUSK_TAB_ID" ] || [ -z "$NEW_HUSK_PANE_ID" ]; then
|
|
160
|
+
fail "husk close-and-replace did not return new tab/pane ids"
|
|
161
|
+
fi
|
|
162
|
+
[ "$NEW_HUSK_PANE_ID" != "$HUSK_PANE_ID" ] || fail "husk close-and-replace returned the SAME pane id - it did not actually replace anything"
|
|
163
|
+
if herdr pane get "$HUSK_PANE_ID" --session "$SESSION" >/dev/null 2>&1; then
|
|
164
|
+
fail "REGRESSION: the old husk pane should have been closed by close-and-replace, but it still exists"
|
|
165
|
+
fi
|
|
166
|
+
HUSK_WS_TABS=$(herdr tab list --workspace "${CONTAINER#*:}" --session "$SESSION" 2>&1)
|
|
167
|
+
printf '%s' "$HUSK_WS_TABS" | jq -e --arg t "$NEW_HUSK_TAB_ID" '.result.tabs[] | select(.tab_id == $t)' >/dev/null 2>&1 \
|
|
168
|
+
|| fail "REGRESSION: the replacement tab is missing from the workspace's own tab list"
|
|
169
|
+
pass "real herdr: create_task closes and replaces a same-labeled tab whose pane hosts no registered agent (the restored-husk shape), leaving the workspace intact"
|
|
170
|
+
fm_backend_herdr_kill "$SESSION:$NEW_HUSK_PANE_ID"
|
|
171
|
+
|
|
172
|
+
# --- workspace-per-home: a secondmate-shaped home gets its OWN space --------
|
|
173
|
+
# (docs/herdr-backend.md "Task container shape", AGENTS.md task
|
|
174
|
+
# herdr-sm-spaces-k4). Reuses this suite's own isolated $SESSION - a SECOND,
|
|
175
|
+
# distinct workspace inside the SAME session, never a second session. Placed
|
|
176
|
+
# here (both workspaces' tabs still alive) so the restart-stability check
|
|
177
|
+
# right after it exercises the true multi-workspace shape, not a
|
|
178
|
+
# possibly-emptied-and-auto-closed primary workspace.
|
|
179
|
+
|
|
180
|
+
SM_SCRATCH=$(mktemp -d "${TMPDIR:-/tmp}/fm-herdr-smoke-sm.XXXXXX")
|
|
181
|
+
SM_HOME="$SM_SCRATCH/secondmate-home"
|
|
182
|
+
mkdir -p "$SM_HOME"
|
|
183
|
+
printf 'smoketest-sm1\n' > "$SM_HOME/.fm-secondmate-home"
|
|
184
|
+
|
|
185
|
+
SM_CONTAINER_RAW=$(FM_HOME="$SM_HOME" fm_backend_herdr_container_ensure /tmp) || fail "secondmate-shaped container_ensure failed"
|
|
186
|
+
SM_CONTAINER=${SM_CONTAINER_RAW%%$'\t'*}
|
|
187
|
+
SM_SEEDED_TAB_ID=${SM_CONTAINER_RAW#*$'\t'}
|
|
188
|
+
case "$SM_CONTAINER" in
|
|
189
|
+
"$SESSION":w*) : ;;
|
|
190
|
+
*) fail "secondmate container_ensure returned an unexpected shape: $SM_CONTAINER" ;;
|
|
191
|
+
esac
|
|
192
|
+
[ "$SM_CONTAINER" != "$CONTAINER" ] || fail "a secondmate-shaped home must get a DIFFERENT workspace than the primary's, got the same: $SM_CONTAINER"
|
|
193
|
+
[ -n "$SM_SEEDED_TAB_ID" ] || fail "the secondmate-shaped home's container_ensure must CREATE its own workspace and report its seeded default tab id"
|
|
194
|
+
pass "real herdr: a secondmate-shaped home (.fm-secondmate-home) gets its OWN herdr workspace, distinct from the primary's, in the SAME session"
|
|
195
|
+
|
|
196
|
+
SM_WSID=${SM_CONTAINER#*:}
|
|
197
|
+
SM_LABEL_REAL=$(herdr workspace list --session "$SESSION" 2>&1 | jq -r --arg id "$SM_WSID" '.result.workspaces[]? | select(.workspace_id == $id) | .label')
|
|
198
|
+
[ "$SM_LABEL_REAL" = "2ndmate-smoketest-sm1" ] || fail "the secondmate workspace's real herdr label should be 2ndmate-smoketest-sm1, got '$SM_LABEL_REAL'"
|
|
199
|
+
pass "real herdr: the secondmate-shaped home's workspace is labeled 2ndmate-<secondmate-id> in herdr itself"
|
|
200
|
+
|
|
201
|
+
SM_TASK_LABEL="fm-smtask1"
|
|
202
|
+
SM_TASK_IDS=$(FM_HOME="$SM_HOME" fm_backend_herdr_create_task "$SM_CONTAINER" "$SM_TASK_LABEL" /tmp "$SM_SEEDED_TAB_ID") || fail "secondmate create_task failed"
|
|
203
|
+
read -r SM_TAB_ID SM_PANE_ID <<EOF
|
|
204
|
+
$SM_TASK_IDS
|
|
205
|
+
EOF
|
|
206
|
+
if [ -z "$SM_TAB_ID" ] || [ -z "$SM_PANE_ID" ]; then
|
|
207
|
+
fail "secondmate create_task did not return tab/pane ids"
|
|
208
|
+
fi
|
|
209
|
+
pass "real herdr: a task spawned into the secondmate-shaped home lands as a tab inside the secondmate's OWN workspace"
|
|
210
|
+
|
|
211
|
+
# list_live for each home must never see the OTHER home's task.
|
|
212
|
+
PRIMARY_LIVE=$(fm_backend_herdr_list_live "$SESSION")
|
|
213
|
+
case "$PRIMARY_LIVE" in
|
|
214
|
+
*"$SM_TASK_LABEL"*) fail "the primary home's list_live must not see a secondmate-shaped home's task"$'\n'"$PRIMARY_LIVE" ;;
|
|
215
|
+
esac
|
|
216
|
+
SM_LIVE=$(FM_HOME="$SM_HOME" fm_backend_herdr_list_live "$SESSION")
|
|
217
|
+
case "$SM_LIVE" in
|
|
218
|
+
*"$SM_TASK_LABEL"*) : ;;
|
|
219
|
+
*) fail "the secondmate-shaped home's list_live did not see its own task"$'\n'"$SM_LIVE" ;;
|
|
220
|
+
esac
|
|
221
|
+
case "$SM_LIVE" in
|
|
222
|
+
*"$LABEL"*) fail "the secondmate-shaped home's list_live must not see the primary's task ($LABEL)"$'\n'"$SM_LIVE" ;;
|
|
223
|
+
esac
|
|
224
|
+
pass "real herdr: list_live stays scoped to each home's own workspace - neither home sees the other's tasks"
|
|
225
|
+
|
|
226
|
+
# --- restart stability in the MULTI-workspace shape --------------------------
|
|
227
|
+
# P2 (herdr-verification-p2.md "ID stability") verified this for a single
|
|
228
|
+
# workspace only. Both this suite's workspaces (and their tabs/panes) must
|
|
229
|
+
# still resolve, unchanged, after a `session stop` + fresh server restart, all
|
|
230
|
+
# scoped to this suite's OWN isolated $SESSION - never the default session.
|
|
231
|
+
|
|
232
|
+
fm_herdr_lab_stop "$SESSION" >/dev/null 2>&1 \
|
|
233
|
+
|| fail "could not stop the isolated session for the restart-stability check"
|
|
234
|
+
sleep 0.5
|
|
235
|
+
fm_backend_herdr_server_ensure "$SESSION" || fail "the isolated session's server did not come back up after the stop"
|
|
236
|
+
|
|
237
|
+
POST_LIST=$(herdr workspace list --session "$SESSION" 2>&1)
|
|
238
|
+
POST_PRIMARY_ID=$(printf '%s' "$POST_LIST" | jq -r '.result.workspaces[]? | select(.label == "firstmate") | .workspace_id')
|
|
239
|
+
POST_SM_ID=$(printf '%s' "$POST_LIST" | jq -r --arg l "2ndmate-smoketest-sm1" '.result.workspaces[]? | select(.label == $l) | .workspace_id')
|
|
240
|
+
[ "$POST_PRIMARY_ID" = "${CONTAINER#*:}" ] || fail "the primary workspace id did not survive the restart: before=${CONTAINER#*:} after=$POST_PRIMARY_ID"
|
|
241
|
+
[ "$POST_SM_ID" = "$SM_WSID" ] || fail "the secondmate workspace id did not survive the restart: before=$SM_WSID after=$POST_SM_ID"
|
|
242
|
+
|
|
243
|
+
POST_PANE=$(herdr pane get "$PANE_ID" --session "$SESSION" 2>/dev/null | jq -r '.result.pane.pane_id // empty')
|
|
244
|
+
[ "$POST_PANE" = "$PANE_ID" ] || fail "the primary task's pane id did not survive the restart: before=$PANE_ID after=$POST_PANE"
|
|
245
|
+
POST_SM_PANE=$(herdr pane get "$SM_PANE_ID" --session "$SESSION" 2>/dev/null | jq -r '.result.pane.pane_id // empty')
|
|
246
|
+
[ "$POST_SM_PANE" = "$SM_PANE_ID" ] || fail "the secondmate task's pane id did not survive the restart: before=$SM_PANE_ID after=$POST_SM_PANE"
|
|
247
|
+
pass "real herdr: BOTH workspace ids/labels AND both tasks' pane ids survive a session stop + fresh server restart (multi-workspace shape)"
|
|
248
|
+
|
|
249
|
+
fm_backend_herdr_kill "$SESSION:$SM_PANE_ID"
|
|
250
|
+
|
|
251
|
+
# --- send_text_line (atomic run) ---------------------------------------------
|
|
252
|
+
|
|
253
|
+
fm_backend_herdr_send_text_line "$TARGET" "echo captain-on-deck-line" \
|
|
254
|
+
|| fail "send_text_line failed"
|
|
255
|
+
sleep 0.5
|
|
256
|
+
out=$(fm_backend_herdr_capture "$TARGET" 20) || fail "capture failed after send_text_line"
|
|
257
|
+
case "$out" in
|
|
258
|
+
*captain-on-deck-line*) : ;;
|
|
259
|
+
*) fail "real herdr: send_text_line did not run and echo the line"$'\n'"$out" ;;
|
|
260
|
+
esac
|
|
261
|
+
pass "real herdr: send_text_line runs a command atomically (pane run) and its output is capturable"
|
|
262
|
+
|
|
263
|
+
# --- send_literal + send_key(Enter), the two-step launch-command form -------
|
|
264
|
+
|
|
265
|
+
fm_backend_herdr_send_literal "$TARGET" 'echo literal-then-key-captain' \
|
|
266
|
+
|| fail "send_literal failed"
|
|
267
|
+
sleep 0.2
|
|
268
|
+
fm_backend_herdr_send_key "$TARGET" Enter || fail "send_key Enter failed"
|
|
269
|
+
sleep 0.5
|
|
270
|
+
out=$(fm_backend_herdr_capture "$TARGET" 20) || fail "capture failed after send_literal+send_key"
|
|
271
|
+
case "$out" in
|
|
272
|
+
*literal-then-key-captain*) : ;;
|
|
273
|
+
*) fail "real herdr: send_literal + send_key(Enter) did not submit and echo the line"$'\n'"$out" ;;
|
|
274
|
+
esac
|
|
275
|
+
pass "real herdr: send_literal + send_key Enter submit as two separate steps (verified: send-text does NOT auto-submit)"
|
|
276
|
+
|
|
277
|
+
# --- current_path -------------------------------------------------------------
|
|
278
|
+
|
|
279
|
+
fm_backend_herdr_send_text_line "$TARGET" "cd /tmp"
|
|
280
|
+
sleep 0.3
|
|
281
|
+
p=$(fm_backend_herdr_current_path "$TARGET") || fail "current_path failed"
|
|
282
|
+
case "$p" in
|
|
283
|
+
*/tmp) : ;;
|
|
284
|
+
*) fail "real herdr: current_path did not report the pane's cwd after cd /tmp, got '$p'" ;;
|
|
285
|
+
esac
|
|
286
|
+
pass "real herdr: current_path reads the pane's live cwd"
|
|
287
|
+
|
|
288
|
+
# --- busy_state on a real claude harness (verified in herdr-verification-p2.md) ---
|
|
289
|
+
|
|
290
|
+
if [ "${FM_HERDR_SMOKE_REAL_CLAUDE:-0}" = 1 ] && command -v claude >/dev/null 2>&1; then
|
|
291
|
+
fm_backend_herdr_send_literal "$TARGET" "CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION=false claude --dangerously-skip-permissions --print 'say the word HERDRSMOKEOK and nothing else'"
|
|
292
|
+
sleep 0.2
|
|
293
|
+
fm_backend_herdr_send_key "$TARGET" Enter
|
|
294
|
+
found_working=0
|
|
295
|
+
for _ in $(seq 1 20); do
|
|
296
|
+
bs=$(fm_backend_herdr_busy_state "$TARGET" 2>/dev/null)
|
|
297
|
+
[ "$bs" = busy ] && { found_working=1; break; }
|
|
298
|
+
[ "$bs" = idle ] && break
|
|
299
|
+
sleep 0.5
|
|
300
|
+
done
|
|
301
|
+
[ "$found_working" -eq 1 ] || echo "note: never observed agent_status=working for the real claude run (timing-dependent, not fatal)" >&2
|
|
302
|
+
# Wait for completion regardless, bounded.
|
|
303
|
+
for _ in $(seq 1 40); do
|
|
304
|
+
bs=$(fm_backend_herdr_busy_state "$TARGET" 2>/dev/null)
|
|
305
|
+
[ "$bs" = idle ] && break
|
|
306
|
+
sleep 0.5
|
|
307
|
+
done
|
|
308
|
+
out=$(fm_backend_herdr_capture "$TARGET" 30)
|
|
309
|
+
case "$out" in
|
|
310
|
+
*HERDRSMOKEOK*) pass "real herdr: agent_status busy/idle detection tracks a real claude turn, and capture shows its output" ;;
|
|
311
|
+
*) echo "note: claude output marker not observed within the bound (timing-dependent, not fatal to this smoke suite)" >&2 ;;
|
|
312
|
+
esac
|
|
313
|
+
elif [ "${FM_HERDR_SMOKE_REAL_CLAUDE:-0}" != 1 ]; then
|
|
314
|
+
echo "note: FM_HERDR_SMOKE_REAL_CLAUDE=1 not set; skipping the real-agent busy_state check" >&2
|
|
315
|
+
else
|
|
316
|
+
echo "note: claude not installed; skipping the real-agent busy_state check" >&2
|
|
317
|
+
fi
|
|
318
|
+
|
|
319
|
+
# --- kill -----------------------------------------------------------------
|
|
320
|
+
|
|
321
|
+
fm_backend_herdr_kill "$TARGET"
|
|
322
|
+
if herdr pane get "$PANE_ID" --session "$SESSION" >/dev/null 2>&1; then
|
|
323
|
+
fail "kill did not remove the pane"
|
|
324
|
+
fi
|
|
325
|
+
# Best-effort contract: killing an already-gone pane must not error.
|
|
326
|
+
fm_backend_herdr_kill "$TARGET" || fail "kill on an already-dead target must stay best-effort (never fail)"
|
|
327
|
+
pass "real herdr: kill removes the pane and is idempotent/best-effort"
|
|
328
|
+
|
|
329
|
+
# --- list_live (label-based recovery discovery) ------------------------------
|
|
330
|
+
|
|
331
|
+
# Real firstmate spawns always re-run container_ensure immediately before
|
|
332
|
+
# create_task (bin/fm-spawn.sh), never reusing a container reference from an
|
|
333
|
+
# earlier spawn. This test must do the same: the kill above closed the only
|
|
334
|
+
# remaining tab in $CONTAINER's workspace, and closing a workspace's last tab
|
|
335
|
+
# deletes the workspace itself (verified real-herdr behavior), so the stale
|
|
336
|
+
# $CONTAINER from container_ensure at test start no longer names a live
|
|
337
|
+
# workspace.
|
|
338
|
+
CONTAINER_RAW=$(fm_backend_herdr_container_ensure /tmp) || fail "container_ensure for the second task failed"
|
|
339
|
+
CONTAINER=${CONTAINER_RAW%%$'\t'*}
|
|
340
|
+
SEEDED_TAB_ID=${CONTAINER_RAW#*$'\t'}
|
|
341
|
+
[ -n "$SEEDED_TAB_ID" ] || fail "the workspace was deleted when its last tab was killed, so this container_ensure must CREATE a fresh one and report its seeded default tab id"
|
|
342
|
+
LABEL2="fm-smoke2"
|
|
343
|
+
TASK_IDS2=$(fm_backend_herdr_create_task "$CONTAINER" "$LABEL2" /tmp "$SEEDED_TAB_ID") || fail "second create_task failed"
|
|
344
|
+
read -r _TAB_ID2 PANE_ID2 <<EOF
|
|
345
|
+
$TASK_IDS2
|
|
346
|
+
EOF
|
|
347
|
+
live=$(fm_backend_herdr_list_live "$SESSION")
|
|
348
|
+
assert_contains_local() { case "$1" in *"$2"*) : ;; *) fail "$3"$'\n'"--- got ---"$'\n'"$1" ;; esac; }
|
|
349
|
+
assert_contains_local "$live" "$LABEL2" "list_live did not report the freshly created task tab by label"
|
|
350
|
+
pass "real herdr: list_live discovers a live task tab by fm-<id> label"
|
|
351
|
+
|
|
352
|
+
fm_backend_herdr_kill "$SESSION:$PANE_ID2"
|
|
353
|
+
|
|
354
|
+
cleanup_all
|
|
355
|
+
trap - EXIT
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# tests/fm-backend-herdr-workspace-per-home-e2e.test.sh - mandatory ISOLATED
|
|
3
|
+
# end-to-end real-herdr test for the P3 "workspace-per-home" pass (AGENTS.md
|
|
4
|
+
# task herdr-sm-spaces-k4). Drives the REAL bin/fm-spawn.sh and
|
|
5
|
+
# bin/fm-teardown.sh (not just adapter primitives), because the requirement
|
|
6
|
+
# under test - a --secondmate spawn's tab landing in the secondmate's OWN
|
|
7
|
+
# herdr workspace, and a crewmate spawned FROM a secondmate home landing there
|
|
8
|
+
# too - only exists at fm-spawn.sh's own home-shadowing logic (the herdr case
|
|
9
|
+
# arm) and at fm_backend_herdr_workspace_label's FM_HOME read; neither is
|
|
10
|
+
# exercised by the adapter-primitive smoke test.
|
|
11
|
+
#
|
|
12
|
+
# Mirrors tests/fm-backend-autodetect-smoke.test.sh's isolated-session
|
|
13
|
+
# convention: a private throwaway HERDR_SESSION (never the captain's
|
|
14
|
+
# default), scratch FM_HOME(s), and scratch local-only projects.
|
|
15
|
+
#
|
|
16
|
+
# Safety (2026-07-02 incident, see tests/herdr-test-safety.sh): cleanup uses
|
|
17
|
+
# ONLY herdr_safe_stop_and_delete, never a bare/inline-prefixed `herdr server
|
|
18
|
+
# stop`.
|
|
19
|
+
#
|
|
20
|
+
# Covers, at minimum (per the task brief):
|
|
21
|
+
# - a primary-shaped home (no .fm-secondmate-home marker) spawning a
|
|
22
|
+
# crewmate into the "firstmate" workspace
|
|
23
|
+
# - a secondmate-shaped home (with .fm-secondmate-home) getting its own
|
|
24
|
+
# labeled workspace when the PRIMARY spawns it (fm-spawn.sh's FM_HOME
|
|
25
|
+
# shadow for --secondmate)
|
|
26
|
+
# - a crewmate spawned FROM that secondmate-shaped home (the secondmate
|
|
27
|
+
# running its OWN fm-spawn.sh) landing in the secondmate's own workspace -
|
|
28
|
+
# this exact path has never run before this test
|
|
29
|
+
# - teardown closing the right tab (and no other)
|
|
30
|
+
# - list-live recovery seeing only its own home's tabs, for both homes
|
|
31
|
+
set -u
|
|
32
|
+
|
|
33
|
+
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
34
|
+
|
|
35
|
+
fail() { printf 'not ok - %s\n' "$1" >&2; cleanup_all; exit 1; }
|
|
36
|
+
pass() { printf 'ok - %s\n' "$1"; }
|
|
37
|
+
assert_contains_local() { # <haystack> <needle> <msg>
|
|
38
|
+
case "$1" in
|
|
39
|
+
*"$2"*) : ;;
|
|
40
|
+
*) fail "$3"$'\n'"--- got ---"$'\n'"$1" ;;
|
|
41
|
+
esac
|
|
42
|
+
}
|
|
43
|
+
assert_not_contains_local() { # <haystack> <needle> <msg>
|
|
44
|
+
case "$1" in
|
|
45
|
+
*"$2"*) fail "$3"$'\n'"--- got ---"$'\n'"$1" ;;
|
|
46
|
+
*) : ;;
|
|
47
|
+
esac
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
command -v herdr >/dev/null 2>&1 || { echo "skip: herdr not found"; exit 0; }
|
|
51
|
+
command -v jq >/dev/null 2>&1 || { echo "skip: jq not found (required by the herdr adapter)"; exit 0; }
|
|
52
|
+
command -v treehouse >/dev/null 2>&1 || { echo "skip: treehouse not found (required by fm-spawn.sh)"; exit 0; }
|
|
53
|
+
|
|
54
|
+
# shellcheck source=tests/herdr-test-safety.sh
|
|
55
|
+
. "$ROOT/tests/herdr-test-safety.sh"
|
|
56
|
+
|
|
57
|
+
# This suite runs against its own isolated lab session, so a Herdr pane
|
|
58
|
+
# inherited from the terminal it was launched in must not follow spawn into it
|
|
59
|
+
# as a cross-session parent identity (tests/herdr-test-safety.sh).
|
|
60
|
+
herdr_forget_inherited_pane
|
|
61
|
+
|
|
62
|
+
# TMP_ROOT is physically resolved (mktemp -d "$(pwd -P)"-relative) for the same
|
|
63
|
+
# low-noise scratch fixture shape used by
|
|
64
|
+
# tests/fm-backend-autodetect-smoke.test.sh.
|
|
65
|
+
# fm-spawn no longer needs this as a symlink workaround: fm-spawn-symlink-guard-s8
|
|
66
|
+
# canonicalized project and backend cwd comparisons in the worktree-discovery
|
|
67
|
+
# poll.
|
|
68
|
+
TMP_ROOT=$(mktemp -d "$(cd "${TMPDIR:-/tmp}" && pwd -P)/fm-herdr-e2e.XXXXXX")
|
|
69
|
+
SESSION="fm-lab-herdr-e2e-$$"
|
|
70
|
+
export HERDR_SESSION="$SESSION"
|
|
71
|
+
WT1=; WT2=
|
|
72
|
+
cleanup_all() {
|
|
73
|
+
[ -n "$WT1" ] && command -v treehouse >/dev/null 2>&1 && treehouse return --force "$WT1" >/dev/null 2>&1
|
|
74
|
+
[ -n "$WT2" ] && command -v treehouse >/dev/null 2>&1 && treehouse return --force "$WT2" >/dev/null 2>&1
|
|
75
|
+
herdr_safe_stop_and_delete "$SESSION"
|
|
76
|
+
rm -rf "$TMP_ROOT"
|
|
77
|
+
}
|
|
78
|
+
trap cleanup_all EXIT
|
|
79
|
+
fm_herdr_lab_prepare "$SESSION" || fail "could not prepare isolated Herdr lab session"
|
|
80
|
+
|
|
81
|
+
# shellcheck source=/dev/null
|
|
82
|
+
. "$ROOT/bin/fm-backend.sh"
|
|
83
|
+
fm_backend_source herdr || fail "fm_backend_source herdr failed"
|
|
84
|
+
|
|
85
|
+
# --- scratch world: a primary-shaped home, a secondmate-shaped home, two projects ---
|
|
86
|
+
|
|
87
|
+
# This test asserts the per-home FLAT workspace shape, so both homes opt out of
|
|
88
|
+
# the default-on presentation projection rather than depending on that default.
|
|
89
|
+
PRIMARY_HOME="$TMP_ROOT/primary-home"
|
|
90
|
+
mkdir -p "$PRIMARY_HOME/state" "$PRIMARY_HOME/data/cm1" "$PRIMARY_HOME/config"
|
|
91
|
+
printf 'off\n' > "$PRIMARY_HOME/config/herdr-presentation-spaces"
|
|
92
|
+
printf 'trivial e2e primary crewmate brief: nothing to do.\n' > "$PRIMARY_HOME/data/cm1/brief.md"
|
|
93
|
+
|
|
94
|
+
SM_HOME="$TMP_ROOT/secondmate-home"
|
|
95
|
+
mkdir -p "$SM_HOME/state" "$SM_HOME/data/cm2" "$SM_HOME/config" "$SM_HOME/projects" "$SM_HOME/bin"
|
|
96
|
+
printf 'off\n' > "$SM_HOME/config/herdr-presentation-spaces"
|
|
97
|
+
printf '# scratch secondmate home AGENTS.md placeholder\n' > "$SM_HOME/AGENTS.md"
|
|
98
|
+
printf 'e2esm1\n' > "$SM_HOME/.fm-secondmate-home"
|
|
99
|
+
printf 'trivial e2e secondmate charter: nothing to do.\n' > "$SM_HOME/data/charter.md"
|
|
100
|
+
printf 'trivial e2e secondmate-owned crewmate brief: nothing to do.\n' > "$SM_HOME/data/cm2/brief.md"
|
|
101
|
+
|
|
102
|
+
make_scratch_project() { # <dir>
|
|
103
|
+
local dir=$1
|
|
104
|
+
mkdir -p "$dir"
|
|
105
|
+
git -C "$dir" init -q
|
|
106
|
+
printf '# scratch\n' > "$dir/README.md"
|
|
107
|
+
git -C "$dir" add README.md
|
|
108
|
+
git -C "$dir" -c user.name='Firstmate Tests' -c user.email='tests@example.invalid' commit -qm initial
|
|
109
|
+
git clone --quiet --bare "$dir" "$dir.origin.git"
|
|
110
|
+
git -C "$dir" remote add origin "file://$dir.origin.git"
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
PROJ1="$TMP_ROOT/scratch-project-1"; make_scratch_project "$PROJ1"
|
|
114
|
+
PROJ2="$TMP_ROOT/scratch-project-2"; make_scratch_project "$PROJ2"
|
|
115
|
+
|
|
116
|
+
# --- 1. primary-shaped home: a crewmate spawns into the "firstmate" space ---
|
|
117
|
+
|
|
118
|
+
CM1_OUT="$TMP_ROOT/cm1.out"; CM1_ERR="$TMP_ROOT/cm1.err"
|
|
119
|
+
FM_SPAWN_NO_GUARD=1 FM_HOME="$PRIMARY_HOME" FM_ROOT_OVERRIDE="$ROOT" \
|
|
120
|
+
"$ROOT/bin/fm-spawn.sh" cm1 "$PROJ1" "sh -c 'echo primary-crew-ok'" --mode no-mistakes --yolo off --backend herdr \
|
|
121
|
+
>"$CM1_OUT" 2>"$CM1_ERR"
|
|
122
|
+
rc=$?
|
|
123
|
+
[ "$rc" -eq 0 ] || fail "primary-shaped crewmate spawn failed"$'\n'"--- stdout ---"$'\n'"$(cat "$CM1_OUT")"$'\n'"--- stderr ---"$'\n'"$(cat "$CM1_ERR")"
|
|
124
|
+
|
|
125
|
+
CM1_META="$PRIMARY_HOME/state/cm1.meta"
|
|
126
|
+
[ -f "$CM1_META" ] || fail "no meta written for cm1"
|
|
127
|
+
assert_contains_local "$(cat "$CM1_META")" "backend=herdr" "cm1 meta missing backend=herdr"
|
|
128
|
+
WT1=$(grep '^worktree=' "$CM1_META" | cut -d= -f2-)
|
|
129
|
+
CM1_PANE=$(grep '^herdr_pane_id=' "$CM1_META" | cut -d= -f2-)
|
|
130
|
+
[ -n "$CM1_PANE" ] || fail "cm1 meta missing herdr_pane_id"
|
|
131
|
+
pass "real herdr E2E: a primary-shaped home spawns a crewmate on the herdr backend"
|
|
132
|
+
|
|
133
|
+
sleep 1
|
|
134
|
+
CM1_CAPTURE=$(fm_backend_herdr_capture "$SESSION:$CM1_PANE" 30) || fail "capture failed on cm1's pane"
|
|
135
|
+
assert_contains_local "$CM1_CAPTURE" "primary-crew-ok" "cm1's raw launch command did not run in its herdr pane"
|
|
136
|
+
|
|
137
|
+
CM1_WSID=$(herdr pane get "$CM1_PANE" --session "$SESSION" 2>/dev/null | jq -r '.result.pane.workspace_id // empty')
|
|
138
|
+
[ -n "$CM1_WSID" ] || fail "could not read cm1's pane workspace_id"
|
|
139
|
+
CM1_WS_LABEL=$(herdr workspace list --session "$SESSION" 2>&1 | jq -r --arg id "$CM1_WSID" '.result.workspaces[]? | select(.workspace_id == $id) | .label')
|
|
140
|
+
[ "$CM1_WS_LABEL" = "firstmate" ] || fail "a primary-shaped home's crewmate should land in the 'firstmate' workspace, got '$CM1_WS_LABEL'"
|
|
141
|
+
pass "real herdr E2E: the primary-shaped home's crewmate landed in the 'firstmate' workspace"
|
|
142
|
+
|
|
143
|
+
# --- 2. the PRIMARY spawns a secondmate: its tab lands in the SECONDMATE's own space ---
|
|
144
|
+
# (fm-spawn.sh's herdr case arm shadows FM_HOME to the secondmate's home for
|
|
145
|
+
# exactly this call - AGENTS.md task herdr-sm-spaces-k4, requirement 3.)
|
|
146
|
+
|
|
147
|
+
SM_OUT="$TMP_ROOT/sm.out"; SM_ERR="$TMP_ROOT/sm.err"
|
|
148
|
+
FM_SPAWN_NO_GUARD=1 FM_HOME="$PRIMARY_HOME" FM_ROOT_OVERRIDE="$ROOT" \
|
|
149
|
+
"$ROOT/bin/fm-spawn.sh" e2esm1 "$SM_HOME" "sh -c 'echo secondmate-launch-ok'" --secondmate --backend herdr \
|
|
150
|
+
>"$SM_OUT" 2>"$SM_ERR"
|
|
151
|
+
rc=$?
|
|
152
|
+
[ "$rc" -eq 0 ] || fail "the primary's --secondmate spawn of e2esm1 failed"$'\n'"--- stdout ---"$'\n'"$(cat "$SM_OUT")"$'\n'"--- stderr ---"$'\n'"$(cat "$SM_ERR")"
|
|
153
|
+
|
|
154
|
+
SM_META="$PRIMARY_HOME/state/e2esm1.meta"
|
|
155
|
+
[ -f "$SM_META" ] || fail "no meta written for e2esm1 (recorded in the PRIMARY's own state dir, since the primary did the spawning)"
|
|
156
|
+
assert_contains_local "$(cat "$SM_META")" "kind=secondmate" "e2esm1 meta missing kind=secondmate"
|
|
157
|
+
assert_contains_local "$(cat "$SM_META")" "backend=herdr" "e2esm1 meta missing backend=herdr"
|
|
158
|
+
assert_contains_local "$(cat "$SM_META")" "home=$SM_HOME" "e2esm1 meta does not record its own home"
|
|
159
|
+
SM_PANE=$(grep '^herdr_pane_id=' "$SM_META" | cut -d= -f2-)
|
|
160
|
+
[ -n "$SM_PANE" ] || fail "e2esm1 meta missing herdr_pane_id"
|
|
161
|
+
pass "real herdr E2E: the primary spawns a --secondmate task on the herdr backend"
|
|
162
|
+
|
|
163
|
+
SM_WSID=$(herdr pane get "$SM_PANE" --session "$SESSION" 2>/dev/null | jq -r '.result.pane.workspace_id // empty')
|
|
164
|
+
[ -n "$SM_WSID" ] || fail "could not read e2esm1's pane workspace_id"
|
|
165
|
+
[ "$SM_WSID" != "$CM1_WSID" ] || fail "the secondmate's tab must NOT land in the primary's workspace, but it shares $CM1_WSID"
|
|
166
|
+
SM_WS_LABEL=$(herdr workspace list --session "$SESSION" 2>&1 | jq -r --arg id "$SM_WSID" '.result.workspaces[]? | select(.workspace_id == $id) | .label')
|
|
167
|
+
[ "$SM_WS_LABEL" = "2ndmate-e2esm1" ] || fail "a --secondmate spawn should land in '2ndmate-<id>', got '$SM_WS_LABEL'"
|
|
168
|
+
pass "real herdr E2E: a --secondmate spawn by the PRIMARY lands in the SECONDMATE's own labeled workspace, distinct from the primary's"
|
|
169
|
+
|
|
170
|
+
# --- 3. a crewmate spawned FROM the secondmate-shaped home lands in the SAME
|
|
171
|
+
# secondmate workspace (this exact path has never run before this test) -----
|
|
172
|
+
|
|
173
|
+
CM2_OUT="$TMP_ROOT/cm2.out"; CM2_ERR="$TMP_ROOT/cm2.err"
|
|
174
|
+
FM_SPAWN_NO_GUARD=1 FM_HOME="$SM_HOME" FM_ROOT_OVERRIDE="$ROOT" \
|
|
175
|
+
"$ROOT/bin/fm-spawn.sh" cm2 "$PROJ2" "sh -c 'echo sm-crew-ok'" --mode no-mistakes --yolo off --backend herdr \
|
|
176
|
+
>"$CM2_OUT" 2>"$CM2_ERR"
|
|
177
|
+
rc=$?
|
|
178
|
+
[ "$rc" -eq 0 ] || fail "a crewmate spawned FROM the secondmate-shaped home failed"$'\n'"--- stdout ---"$'\n'"$(cat "$CM2_OUT")"$'\n'"--- stderr ---"$'\n'"$(cat "$CM2_ERR")"
|
|
179
|
+
|
|
180
|
+
CM2_META="$SM_HOME/state/cm2.meta"
|
|
181
|
+
[ -f "$CM2_META" ] || fail "no meta written for cm2 (recorded in the SECONDMATE's own state dir - it did its own spawning)"
|
|
182
|
+
assert_contains_local "$(cat "$CM2_META")" "backend=herdr" "cm2 meta missing backend=herdr"
|
|
183
|
+
WT2=$(grep '^worktree=' "$CM2_META" | cut -d= -f2-)
|
|
184
|
+
CM2_PANE=$(grep '^herdr_pane_id=' "$CM2_META" | cut -d= -f2-)
|
|
185
|
+
[ -n "$CM2_PANE" ] || fail "cm2 meta missing herdr_pane_id"
|
|
186
|
+
pass "real herdr E2E: a crewmate spawns successfully FROM a secondmate-shaped home's own fm-spawn.sh process"
|
|
187
|
+
|
|
188
|
+
sleep 1
|
|
189
|
+
CM2_CAPTURE=$(fm_backend_herdr_capture "$SESSION:$CM2_PANE" 30) || fail "capture failed on cm2's pane"
|
|
190
|
+
assert_contains_local "$CM2_CAPTURE" "sm-crew-ok" "cm2's raw launch command did not run in its herdr pane"
|
|
191
|
+
|
|
192
|
+
CM2_WSID=$(herdr pane get "$CM2_PANE" --session "$SESSION" 2>/dev/null | jq -r '.result.pane.workspace_id // empty')
|
|
193
|
+
[ "$CM2_WSID" = "$SM_WSID" ] || fail "a crewmate spawned FROM the secondmate home should land in the SAME workspace as the secondmate's own task ($SM_WSID), got '$CM2_WSID'"
|
|
194
|
+
[ "$CM2_WSID" != "$CM1_WSID" ] || fail "a crewmate spawned FROM the secondmate home must NOT land in the primary's workspace"
|
|
195
|
+
pass "real herdr E2E: a crewmate spawned FROM the secondmate-shaped home lands in the secondmate's OWN workspace - falls out of per-home resolution, no glue needed"
|
|
196
|
+
|
|
197
|
+
# --- 4. list-live recovery: each home sees only its own tabs ---------------
|
|
198
|
+
|
|
199
|
+
PRIMARY_LIVE=$(FM_HOME="$PRIMARY_HOME" fm_backend_herdr_list_live "$SESSION")
|
|
200
|
+
assert_contains_local "$PRIMARY_LIVE" "fm-cm1" "the primary home's list_live did not see its own task"
|
|
201
|
+
assert_not_contains_local "$PRIMARY_LIVE" "fm-e2esm1" "the primary home's list_live must not see the secondmate's own task"
|
|
202
|
+
assert_not_contains_local "$PRIMARY_LIVE" "fm-cm2" "the primary home's list_live must not see the secondmate-owned crewmate's task"
|
|
203
|
+
pass "real herdr E2E: list_live from the primary's own context sees only the primary's own task"
|
|
204
|
+
|
|
205
|
+
SM_LIVE=$(FM_HOME="$SM_HOME" fm_backend_herdr_list_live "$SESSION")
|
|
206
|
+
assert_contains_local "$SM_LIVE" "fm-e2esm1" "the secondmate home's list_live did not see its own task"
|
|
207
|
+
assert_contains_local "$SM_LIVE" "fm-cm2" "the secondmate home's list_live did not see the crewmate spawned from it"
|
|
208
|
+
assert_not_contains_local "$SM_LIVE" "fm-cm1" "the secondmate home's list_live must not see the primary's task"
|
|
209
|
+
pass "real herdr E2E: list_live from the secondmate's own context sees only tasks in the secondmate's own workspace (both its own tab and its crewmate's)"
|
|
210
|
+
|
|
211
|
+
# --- 5. teardown closes the RIGHT tab, and no other ------------------------
|
|
212
|
+
|
|
213
|
+
TD1_OUT="$TMP_ROOT/td1.out"
|
|
214
|
+
FM_ROOT_OVERRIDE="$ROOT" FM_STATE_OVERRIDE="$PRIMARY_HOME/state" FM_DATA_OVERRIDE="$PRIMARY_HOME/data" \
|
|
215
|
+
FM_CONFIG_OVERRIDE="$PRIMARY_HOME/config" \
|
|
216
|
+
"$ROOT/bin/fm-teardown.sh" cm1 >"$TD1_OUT" 2>&1
|
|
217
|
+
rc=$?
|
|
218
|
+
[ "$rc" -eq 0 ] || fail "fm-teardown.sh failed for the primary-shaped crewmate cm1"$'\n'"$(cat "$TD1_OUT")"
|
|
219
|
+
[ -f "$CM1_META" ] && fail "fm-teardown.sh did not remove cm1's meta"
|
|
220
|
+
if herdr pane get "$CM1_PANE" --session "$SESSION" >/dev/null 2>&1; then
|
|
221
|
+
fail "fm-teardown.sh did not close cm1's pane"
|
|
222
|
+
fi
|
|
223
|
+
if ! herdr pane get "$SM_PANE" --session "$SESSION" >/dev/null 2>&1; then
|
|
224
|
+
fail "tearing down cm1 must not have closed the secondmate's OWN pane (wrong tab closed)"
|
|
225
|
+
fi
|
|
226
|
+
if ! herdr pane get "$CM2_PANE" --session "$SESSION" >/dev/null 2>&1; then
|
|
227
|
+
fail "tearing down cm1 must not have closed cm2's pane (wrong tab closed)"
|
|
228
|
+
fi
|
|
229
|
+
WT1=
|
|
230
|
+
pass "real herdr E2E: tearing down cm1 closes only its own tab - the secondmate's and cm2's tabs survive untouched"
|
|
231
|
+
|
|
232
|
+
TD2_OUT="$TMP_ROOT/td2.out"
|
|
233
|
+
FM_ROOT_OVERRIDE="$ROOT" FM_STATE_OVERRIDE="$SM_HOME/state" FM_DATA_OVERRIDE="$SM_HOME/data" \
|
|
234
|
+
FM_CONFIG_OVERRIDE="$SM_HOME/config" \
|
|
235
|
+
"$ROOT/bin/fm-teardown.sh" cm2 >"$TD2_OUT" 2>&1
|
|
236
|
+
rc=$?
|
|
237
|
+
[ "$rc" -eq 0 ] || fail "fm-teardown.sh failed for the secondmate-owned crewmate cm2"$'\n'"$(cat "$TD2_OUT")"
|
|
238
|
+
[ -f "$CM2_META" ] && fail "fm-teardown.sh did not remove cm2's meta"
|
|
239
|
+
if herdr pane get "$CM2_PANE" --session "$SESSION" >/dev/null 2>&1; then
|
|
240
|
+
fail "fm-teardown.sh did not close cm2's pane"
|
|
241
|
+
fi
|
|
242
|
+
if ! herdr pane get "$SM_PANE" --session "$SESSION" >/dev/null 2>&1; then
|
|
243
|
+
fail "tearing down cm2 must not have closed the secondmate's OWN pane (wrong tab closed)"
|
|
244
|
+
fi
|
|
245
|
+
WT2=
|
|
246
|
+
pass "real herdr E2E: tearing down cm2 closes only its own tab - the secondmate's own tab (same workspace) survives untouched"
|
|
247
|
+
|
|
248
|
+
fm_backend_herdr_kill "$SESSION:$SM_PANE"
|
|
249
|
+
|
|
250
|
+
cleanup_all
|
|
251
|
+
trap - EXIT
|