@zerwiz/ymir 0.1.4 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/README.md +291 -0
- package/.agents/agents/bragi-marketer.md +111 -0
- package/.agents/agents/brokk.md +352 -0
- package/.agents/agents/forseti-reviewer.md +93 -0
- package/.agents/agents/frigg-consent.md +77 -0
- package/.agents/agents/groa-update.md +77 -0
- package/.agents/agents/hnoss-designer.md +69 -0
- package/.agents/agents/huginn-researcher.md +99 -0
- package/.agents/agents/jord-projects.md +78 -0
- package/.agents/agents/kvasir-scout.md +91 -0
- package/.agents/agents/mimir-planner.md +92 -0
- package/.agents/agents/muninn-stow.md +77 -0
- package/.agents/agents/saga-bearings.md +78 -0
- package/.agents/agents/sindri-developer.md +114 -0
- package/.agents/agents/snotra-documenter.md +105 -0
- package/.agents/agents/syn-recovery.md +78 -0
- package/.agents/agents/tyr-check.md +78 -0
- package/.agents/agents/urdh-hold.md +77 -0
- package/.agents/agents/volundr-smith.md +80 -0
- package/.agents/agents/vor-diagnostics.md +77 -0
- package/.agents/assets/agents/naming.md +50 -0
- package/.agents/assets/agents/registry.md +93 -0
- package/.agents/assets/agents/runtime.md +36 -0
- package/.agents/assets/agents/toon-tasks-cli.md +42 -0
- package/.agents/assets/templates/company_entity.template.md +37 -0
- package/.agents/backend/README.md +74 -0
- package/.agents/backend/backends/cmux.sh +649 -0
- package/.agents/backend/backends/herdr-eventwait.py +157 -0
- package/.agents/backend/backends/herdr-workspace-move.py +114 -0
- package/.agents/backend/backends/herdr.sh +3386 -0
- package/.agents/backend/backends/orca.sh +290 -0
- package/.agents/backend/backends/tmux.sh +357 -0
- package/.agents/backend/backends/zellij.sh +700 -0
- package/.agents/backend/fm-afk-launch.sh +654 -0
- package/.agents/backend/fm-afk-return.sh +241 -0
- package/.agents/backend/fm-afk-start.sh +172 -0
- package/.agents/backend/fm-arm-command-policy.mjs +960 -0
- package/.agents/backend/fm-arm-pretool-check.sh +200 -0
- package/.agents/backend/fm-backend-hometag-lib.sh +52 -0
- package/.agents/backend/fm-backend.sh +981 -0
- package/.agents/backend/fm-backlog-handoff.sh +909 -0
- package/.agents/backend/fm-backlog-receive.sh +187 -0
- package/.agents/backend/fm-backlog-transition-lib.sh +779 -0
- package/.agents/backend/fm-bearings-board.sh +204 -0
- package/.agents/backend/fm-bearings-snapshot.sh +546 -0
- package/.agents/backend/fm-bootstrap.sh +1568 -0
- package/.agents/backend/fm-branch-outcome.sh +203 -0
- package/.agents/backend/fm-branch-prompt.sh +101 -0
- package/.agents/backend/fm-brief.sh +452 -0
- package/.agents/backend/fm-busy-event.sh +234 -0
- package/.agents/backend/fm-busy-lib.sh +986 -0
- package/.agents/backend/fm-captain-hold.sh +1001 -0
- package/.agents/backend/fm-cd-command-policy.mjs +153 -0
- package/.agents/backend/fm-cd-pretool-check.sh +190 -0
- package/.agents/backend/fm-check-lib.sh +74 -0
- package/.agents/backend/fm-check-register.sh +42 -0
- package/.agents/backend/fm-check-unregister.sh +52 -0
- package/.agents/backend/fm-classify-lib.sh +1770 -0
- package/.agents/backend/fm-claude-stop-autoarm.sh +334 -0
- package/.agents/backend/fm-composer-lib.sh +1416 -0
- package/.agents/backend/fm-config-inherit-lib.sh +1202 -0
- package/.agents/backend/fm-config-push.sh +254 -0
- package/.agents/backend/fm-control-lib.sh +251 -0
- package/.agents/backend/fm-control.sh +878 -0
- package/.agents/backend/fm-crew-state.sh +625 -0
- package/.agents/backend/fm-cursor-lib.sh +243 -0
- package/.agents/backend/fm-decision-hold.sh +232 -0
- package/.agents/backend/fm-doc-audience-check.sh +269 -0
- package/.agents/backend/fm-dod-lib.sh +67 -0
- package/.agents/backend/fm-ensure-agents-md.sh +253 -0
- package/.agents/backend/fm-extension-launch-barrier.mjs +129 -0
- package/.agents/backend/fm-extension.mjs +2577 -0
- package/.agents/backend/fm-extension.sh +16 -0
- package/.agents/backend/fm-ff-lib.sh +420 -0
- package/.agents/backend/fm-fleet-snapshot.sh +1463 -0
- package/.agents/backend/fm-fleet-sync.sh +458 -0
- package/.agents/backend/fm-fleet-view.sh +96 -0
- package/.agents/backend/fm-gate-refuse-lib.sh +102 -0
- package/.agents/backend/fm-guard.sh +242 -0
- package/.agents/backend/fm-harness.sh +195 -0
- package/.agents/backend/fm-herdr-ci-cleanup.sh +115 -0
- package/.agents/backend/fm-herdr-lab.sh +346 -0
- package/.agents/backend/fm-herdr-session-cleanup.sh +337 -0
- package/.agents/backend/fm-home-seed.sh +984 -0
- package/.agents/backend/fm-home-summary-refresh.sh +255 -0
- package/.agents/backend/fm-hook-host-lib.sh +36 -0
- package/.agents/backend/fm-inactive-reconcile.sh +531 -0
- package/.agents/backend/fm-inbox.sh +399 -0
- package/.agents/backend/fm-install-actionlint.sh +84 -0
- package/.agents/backend/fm-install-herdr.sh +96 -0
- package/.agents/backend/fm-install-shellcheck.sh +84 -0
- package/.agents/backend/fm-install-treehouse.sh +95 -0
- package/.agents/backend/fm-kimi-turnend-hook.sh +276 -0
- package/.agents/backend/fm-lease-lib.sh +218 -0
- package/.agents/backend/fm-lease.sh +189 -0
- package/.agents/backend/fm-line-cap-lib.sh +51 -0
- package/.agents/backend/fm-lint-workflows.sh +137 -0
- package/.agents/backend/fm-lint.sh +591 -0
- package/.agents/backend/fm-lock-lib.sh +104 -0
- package/.agents/backend/fm-lock.sh +107 -0
- package/.agents/backend/fm-marker-lib.sh +12 -0
- package/.agents/backend/fm-merge-local.sh +74 -0
- package/.agents/backend/fm-merge-outcome-lib.sh +138 -0
- package/.agents/backend/fm-nm-run-lib.sh +124 -0
- package/.agents/backend/fm-on.sh +125 -0
- package/.agents/backend/fm-operational-input.sh +253 -0
- package/.agents/backend/fm-peek.sh +46 -0
- package/.agents/backend/fm-pending-reply-lib.sh +1409 -0
- package/.agents/backend/fm-pr-check.sh +135 -0
- package/.agents/backend/fm-pr-lib.sh +1016 -0
- package/.agents/backend/fm-pr-merge.sh +707 -0
- package/.agents/backend/fm-pr-poll.sh +110 -0
- package/.agents/backend/fm-primary-scope-lib.sh +33 -0
- package/.agents/backend/fm-procevent-extension-capture.pl +259 -0
- package/.agents/backend/fm-procevent-lavish.sh +628 -0
- package/.agents/backend/fm-procevent-lib.sh +892 -0
- package/.agents/backend/fm-procevent-quota.sh +290 -0
- package/.agents/backend/fm-procevent-remote-reply.sh +577 -0
- package/.agents/backend/fm-procevent-when.sh +504 -0
- package/.agents/backend/fm-procevent.sh +1466 -0
- package/.agents/backend/fm-project-mode.sh +92 -0
- package/.agents/backend/fm-project-origin-lib.sh +180 -0
- package/.agents/backend/fm-promote.sh +282 -0
- package/.agents/backend/fm-public-followup-emit.sh +260 -0
- package/.agents/backend/fm-public-followup-lib.sh +398 -0
- package/.agents/backend/fm-public-followup.sh +1330 -0
- package/.agents/backend/fm-push-transition-lib.sh +168 -0
- package/.agents/backend/fm-quota-axi-lib.sh +93 -0
- package/.agents/backend/fm-quota-choose.sh +384 -0
- package/.agents/backend/fm-remote-delta-read.sh +189 -0
- package/.agents/backend/fm-remote-doctor.sh +800 -0
- package/.agents/backend/fm-remote-entrypoint.sh +193 -0
- package/.agents/backend/fm-remote-file.sh +234 -0
- package/.agents/backend/fm-remote-home-provision.sh +259 -0
- package/.agents/backend/fm-remote-home-seed.sh +259 -0
- package/.agents/backend/fm-remote-inherit-push.sh +90 -0
- package/.agents/backend/fm-remote-inherit.sh +179 -0
- package/.agents/backend/fm-remote-job-lib.sh +1241 -0
- package/.agents/backend/fm-remote-job-reap-orphans.sh +137 -0
- package/.agents/backend/fm-remote-job-worker.sh +1124 -0
- package/.agents/backend/fm-remote-readiness-lib.sh +44 -0
- package/.agents/backend/fm-remote-secondmate-control.sh +340 -0
- package/.agents/backend/fm-review-diff.sh +158 -0
- package/.agents/backend/fm-secondmate-charter-lib.sh +44 -0
- package/.agents/backend/fm-secondmate-nudge-lib.sh +68 -0
- package/.agents/backend/fm-secondmate-parent-lib.sh +70 -0
- package/.agents/backend/fm-secondmate-reconcile.sh +371 -0
- package/.agents/backend/fm-secondmate-registry-lib.sh +311 -0
- package/.agents/backend/fm-secondmate-report.sh +88 -0
- package/.agents/backend/fm-send.sh +1059 -0
- package/.agents/backend/fm-session-lock-lib.sh +176 -0
- package/.agents/backend/fm-session-start.sh +970 -0
- package/.agents/backend/fm-sessionstart-cursor.sh +40 -0
- package/.agents/backend/fm-sessionstart-nudge.sh +45 -0
- package/.agents/backend/fm-sessionstart-run.sh +145 -0
- package/.agents/backend/fm-spawn.sh +3153 -0
- package/.agents/backend/fm-startup-memory-budget-lib.sh +224 -0
- package/.agents/backend/fm-startup-memory-budget.sh +94 -0
- package/.agents/backend/fm-startup-network.sh +642 -0
- package/.agents/backend/fm-stow-cascade.sh +251 -0
- package/.agents/backend/fm-subagent-pretool-check.sh +207 -0
- package/.agents/backend/fm-supervise-daemon.sh +1732 -0
- package/.agents/backend/fm-supervision-instructions.sh +215 -0
- package/.agents/backend/fm-supervision-lib.sh +90 -0
- package/.agents/backend/fm-supervisor-target-lib.sh +78 -0
- package/.agents/backend/fm-tangle-lib.sh +53 -0
- package/.agents/backend/fm-task-inbox-lib.sh +402 -0
- package/.agents/backend/fm-tasks-axi-lib.sh +123 -0
- package/.agents/backend/fm-teardown.sh +2922 -0
- package/.agents/backend/fm-test-isolation-proof.sh +588 -0
- package/.agents/backend/fm-test-run.sh +2191 -0
- package/.agents/backend/fm-timeout-lib.sh +141 -0
- package/.agents/backend/fm-timing-lib.sh +179 -0
- package/.agents/backend/fm-tmux-lib.sh +291 -0
- package/.agents/backend/fm-tool-update-check.sh +898 -0
- package/.agents/backend/fm-trace-context-lib.sh +227 -0
- package/.agents/backend/fm-transition-lib.sh +103 -0
- package/.agents/backend/fm-turnend-guard-cursor.sh +391 -0
- package/.agents/backend/fm-turnend-guard-grok.sh +90 -0
- package/.agents/backend/fm-turnend-guard.sh +432 -0
- package/.agents/backend/fm-update.sh +110 -0
- package/.agents/backend/fm-vendor-auth-probe.sh +190 -0
- package/.agents/backend/fm-voice-client.py +1373 -0
- package/.agents/backend/fm-voice-relay.py +1256 -0
- package/.agents/backend/fm-wake-drain.sh +592 -0
- package/.agents/backend/fm-wake-grant.sh +127 -0
- package/.agents/backend/fm-wake-lib.sh +1849 -0
- package/.agents/backend/fm-watch-arm.sh +602 -0
- package/.agents/backend/fm-watch-checkpoint.sh +109 -0
- package/.agents/backend/fm-watch.sh +1962 -0
- package/.agents/backend/fm-x-dismiss.sh +116 -0
- package/.agents/backend/fm-x-followup.sh +286 -0
- package/.agents/backend/fm-x-lib.sh +1000 -0
- package/.agents/backend/fm-x-link.sh +234 -0
- package/.agents/backend/fm-x-poll.sh +185 -0
- package/.agents/backend/fm-x-reply.sh +385 -0
- package/.agents/backend/fm_voice_frame.py +166 -0
- package/.agents/backend/fm_voice_records.py +574 -0
- package/.agents/backend/model-bridge.py +360 -0
- package/.agents/backend/opencode-go-bridge.py +30 -0
- package/.agents/bus/README.md +12 -0
- package/.agents/bus/messages.json +1 -0
- package/.agents/config/agents.machine.example.yaml +16 -0
- package/.agents/config/agents.yaml.example +72 -0
- package/.agents/config/crew-dispatch.json +22 -0
- package/.agents/config/cron.yaml +11 -0
- package/.agents/config/eindri-dispatch.json +67 -0
- package/.agents/config/eindri-harness +1 -0
- package/.agents/config/startup-memory-budget +1 -0
- package/.agents/filebrowser/.filebrowser.json +6 -0
- package/.agents/filebrowser/README.md +11 -0
- package/.agents/gateway/README.md +12 -0
- package/.agents/github/README.md +15 -0
- package/.agents/github/webhooks/.gitkeep +0 -0
- package/.agents/github/workflows/.gitkeep +0 -0
- package/.agents/harness/opencode/plugins/lib/rodd-operational-input.js +37 -0
- package/.agents/harness/opencode/plugins/package.json +4 -0
- package/.agents/harness/opencode/plugins/saga-sessionstart.js +77 -0
- package/.agents/harness/opencode/plugins/syn-cd-check.js +61 -0
- package/.agents/harness/opencode/plugins/syn-pretool-check.js +68 -0
- package/.agents/harness/opencode/plugins/syn-turnend-guard.js +105 -0
- package/.agents/harness/opencode/plugins/syn-watch-arm.js +521 -0
- package/.agents/memory/README.md +46 -0
- package/.agents/memory/runes_audit.md +5 -0
- package/.agents/migrations/0001-hodd-layout.sh +38 -0
- package/.agents/migrations/0002-a2a-mcp.sh +27 -0
- package/.agents/migrations/0003-private-data-separation.sh +121 -0
- package/.agents/migrations/0004-hoard-and-realms.sh +104 -0
- package/.agents/migrations/0005-roots-out-of-tree.sh +158 -0
- package/.agents/sandbox/Dockerfile.utgard +19 -0
- package/.agents/sandbox/README.md +14 -0
- package/.agents/sandbox/utgard.config.json +14 -0
- package/.agents/skills/README.md +59 -0
- package/.agents/skills/bragi-marketing/README.md +3 -0
- package/.agents/skills/bragi-marketing/SKILL.md +82 -0
- package/.agents/skills/eindri-homes/README.md +3 -0
- package/.agents/skills/eindri-homes/SKILL.md +291 -0
- package/.agents/skills/eindri-homes/assets/control-plane.md +122 -0
- package/.agents/skills/eindri-homes/assets/dispatch.md +80 -0
- package/.agents/skills/frigg-consent/README.md +3 -0
- package/.agents/skills/frigg-consent/SKILL.md +56 -0
- package/.agents/skills/galdr-ymirsystem/README.md +3 -0
- package/.agents/skills/galdr-ymirsystem/SKILL.md +159 -0
- package/.agents/skills/galdr-ymirsystem/assets/README.md +74 -0
- package/.agents/skills/galdr-ymirsystem/assets/brokk-distro-runtime.md +390 -0
- package/.agents/skills/galdr-ymirsystem/assets/build-method.md +113 -0
- package/.agents/skills/galdr-ymirsystem/assets/build-tool-categories.md +178 -0
- package/.agents/skills/galdr-ymirsystem/assets/eindri-orchestration.md +518 -0
- package/.agents/skills/galdr-ymirsystem/assets/eindri-profiles.md +136 -0
- package/.agents/skills/galdr-ymirsystem/assets/harness-integration/README.md +736 -0
- package/.agents/skills/galdr-ymirsystem/assets/harness-integration/claude-code.md +197 -0
- package/.agents/skills/galdr-ymirsystem/assets/harness-integration/codex.md +191 -0
- package/.agents/skills/galdr-ymirsystem/assets/harness-integration/cursor.md +193 -0
- package/.agents/skills/galdr-ymirsystem/assets/harness-integration/opencode.md +262 -0
- package/.agents/skills/galdr-ymirsystem/assets/harness-integration/pi.md +295 -0
- package/.agents/skills/galdr-ymirsystem/assets/hlidskjalf-ui.md +539 -0
- package/.agents/skills/galdr-ymirsystem/assets/installation.md +763 -0
- package/.agents/skills/galdr-ymirsystem/assets/local-models/HOST-DATA.example.md +72 -0
- package/.agents/skills/galdr-ymirsystem/assets/local-models.md +274 -0
- package/.agents/skills/galdr-ymirsystem/assets/memory-well.md +163 -0
- package/.agents/skills/galdr-ymirsystem/assets/nornir-jobs.md +415 -0
- package/.agents/skills/galdr-ymirsystem/assets/norse-naming.md +325 -0
- package/.agents/skills/galdr-ymirsystem/assets/odrerir-hall.md +133 -0
- package/.agents/skills/galdr-ymirsystem/assets/pi-boot/einherjar-spawn.schema.json +81 -0
- package/.agents/skills/galdr-ymirsystem/assets/pi-boot/herdr-profile.toml +75 -0
- package/.agents/skills/galdr-ymirsystem/assets/pi-boot/pi-profile.yml +101 -0
- package/.agents/skills/galdr-ymirsystem/assets/pi-boot/supervision-tree.yml +163 -0
- package/.agents/skills/galdr-ymirsystem/assets/pi-boot-guide.md +58 -0
- package/.agents/skills/galdr-ymirsystem/assets/porting-upstream-to-norse.md +301 -0
- package/.agents/skills/galdr-ymirsystem/assets/principles.md +385 -0
- package/.agents/skills/galdr-ymirsystem/assets/reference-adoption.md +99 -0
- package/.agents/skills/galdr-ymirsystem/assets/registry.md +379 -0
- package/.agents/skills/galdr-ymirsystem/assets/runtime-compliance.md +463 -0
- package/.agents/skills/galdr-ymirsystem/assets/runtime-components.md +553 -0
- package/.agents/skills/galdr-ymirsystem/assets/smidja.md +180 -0
- package/.agents/skills/galdr-ymirsystem/schemas/toon-schemas.md +190 -0
- package/.agents/skills/galdr-ymirsystem/scripts/README.md +45 -0
- package/.agents/skills/galdr-ymirsystem/scripts/bench-one.sh +248 -0
- package/.agents/skills/galdr-ymirsystem/scripts/compliance-check.sh +503 -0
- package/.agents/skills/galdr-ymirsystem/scripts/gpu-sample.sh +43 -0
- package/.agents/skills/galdr-ymirsystem/scripts/stop-all.sh +34 -0
- package/.agents/skills/galdr-ymirsystem/scripts/toon-check.py +188 -0
- package/.agents/skills/gjallarhorn-relay/README.md +3 -0
- package/.agents/skills/gjallarhorn-relay/SKILL.md +283 -0
- package/.agents/skills/groa-update/SKILL.md +90 -0
- package/.agents/skills/hamr-adapters/README.md +3 -0
- package/.agents/skills/hamr-adapters/SKILL.md +123 -0
- package/.agents/skills/hamr-adapters/references/common/control-and-recovery.md +37 -0
- package/.agents/skills/hamr-adapters/references/common/dispatch.md +32 -0
- package/.agents/skills/hamr-adapters/references/common/model-and-effort.md +42 -0
- package/.agents/skills/hamr-adapters/references/common/primary-hooks.md +40 -0
- package/.agents/skills/hamr-adapters/references/harness/claude.md +55 -0
- package/.agents/skills/hamr-adapters/references/harness/codex.md +43 -0
- package/.agents/skills/hamr-adapters/references/harness/cursor.md +75 -0
- package/.agents/skills/hamr-adapters/references/harness/grok.md +69 -0
- package/.agents/skills/hamr-adapters/references/harness/kimi.md +51 -0
- package/.agents/skills/hamr-adapters/references/harness/muse.md +70 -0
- package/.agents/skills/hamr-adapters/references/harness/opencode.md +42 -0
- package/.agents/skills/hamr-adapters/references/harness/pi.md +56 -0
- package/.agents/skills/herdr-panes/README.md +3 -0
- package/.agents/skills/herdr-panes/SKILL.md +92 -0
- package/.agents/skills/herdr-panes/assets/herdr-backend.md +346 -0
- package/.agents/skills/herdr-panes/assets/tmux-backend.md +115 -0
- package/.agents/skills/hnoss-design/DESIGN.md +19 -0
- package/.agents/skills/hnoss-design/README.md +3 -0
- package/.agents/skills/hnoss-design/SKILL.md +83 -0
- package/.agents/skills/hvild-afk/README.md +3 -0
- package/.agents/skills/hvild-afk/SKILL.md +241 -0
- package/.agents/skills/jord-projects/README.md +3 -0
- package/.agents/skills/jord-projects/SKILL.md +92 -0
- package/.agents/skills/lifecycle/SKILL.md +56 -0
- package/.agents/skills/lifecycle/smoke_test.sh +57 -0
- package/.agents/skills/lifecycle/start.sh +21 -0
- package/.agents/skills/lifecycle/status.sh +35 -0
- package/.agents/skills/lifecycle/stop.sh +16 -0
- package/.agents/skills/muninn-stow/README.md +3 -0
- package/.agents/skills/muninn-stow/SKILL.md +309 -0
- package/.agents/skills/no-mistakes/SKILL.md +379 -0
- package/.agents/skills/nornir-schedule/README.md +3 -0
- package/.agents/skills/nornir-schedule/SKILL.md +25 -0
- package/.agents/skills/nornir-schedule/assets/events.md +137 -0
- package/.agents/skills/nornir-schedule/assets/quota.md +131 -0
- package/.agents/skills/nsr-compliance/README.md +3 -0
- package/.agents/skills/nsr-compliance/SKILL.md +29 -0
- package/.agents/skills/nsr-compliance/assets/nsr/README.md +40 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/RULES/README.md +15 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/RULES/git-workflow.md +18 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/RULES/security.md +22 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/RULES/tech-stack.md +8 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/SKILL.md +71 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/config/core_four.yaml +16 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/gates/check_danger.sh +102 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/gates/check_wiring.sh +69 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/gates/validate_code.sh +29 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/gates/verify_docs.py +66 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/generate.sh +109 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/harness/envelopes/result_envelope.json +14 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/harness/envelopes/task_envelope.json +20 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/harness/runner.py +303 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/telemetry/logger.py +112 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/README.md +18 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/config/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/gates/README.md +12 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/gates/check_env.sh +23 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/gates/check_paths.sh +20 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/gates/check_platform.sh +23 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/harness/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/harness/envelopes/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/installer/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/installer/install.sh +125 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/telemetry/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/README.md +20 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/features/README.md +36 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/features/SKILL-template.md +14 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/README.md +25 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/SKILL.md +13 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/create_branch.sh +6 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/safe_commit.sh +9 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/sync_upstream.sh +6 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/README.md +27 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/SKILL.md +15 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/smoke_test.sh +12 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/start.sh +19 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/status.sh +12 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/stop.sh +15 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/README.md +18 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/config/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/config/core_four.yaml +13 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/README.md +12 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_danger.sh +102 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_env.sh +23 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_paths.sh +20 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_platform.sh +23 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_wiring.sh +69 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/envelopes/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/envelopes/result_envelope.json +14 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/envelopes/task_envelope.json +20 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/runner.py +303 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/installer/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/installer/install.sh +125 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/telemetry/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/telemetry/logger.py +112 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/BEST_PRACTICES/README.md +14 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/BEST_PRACTICES/api.md +17 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/BEST_PRACTICES/compliance-wiring.md +155 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/BEST_PRACTICES/frontend.md +15 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/README.md +23 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/clients/README.md +16 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/clients/template-README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/deploy.sh +49 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/envs/README.md +12 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/envs/development.env.example +17 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/envs/production.env.example +17 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/envs/staging.env.example +17 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/tenants/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/tenants/template.env.example +8 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/README.md +26 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/agent.md +7 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/developers/dev-1.md +20 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/linux.md +9 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/macos.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/shared.md +19 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/windows.md +14 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/HOSTING/README.md +25 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/HOSTING/_template.md +41 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/HOSTING/hosting-1.md +41 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/README.md +21 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/RUNBOOK/README.md +15 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/RUNBOOK/deployment.md +19 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/RUNBOOK/disaster-recovery.md +15 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/RUNBOOK/ops-tasks.md +14 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/features/README.md +16 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/project-skills.md +146 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/research/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/research/software-compliance-research.md +269 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/working-with-agents.md +260 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/AGENTS.md +38 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/ARCHITECTURE.md +36 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/BEST_PRACTICES.md +27 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/CI_CD.md +23 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/FEATURES.md +15 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/README.md +22 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/RULES.md +37 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/STRUCTURE.md +45 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/TECH_STACK.md +28 -0
- package/.agents/skills/nsr-compliance/assets/nsr/scaffold-spec.md +63 -0
- package/.agents/skills/nsr-compliance/assets/nsr/scripts/scaffold.sh +103 -0
- package/.agents/skills/nsr-compliance/assets/nsr/scripts/validate.sh +52 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/SKILL.md +71 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/config/core_four.yaml +16 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/gates/check_danger.sh +102 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/gates/check_wiring.sh +69 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/gates/validate_code.sh +29 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/gates/verify_docs.py +66 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/generate.sh +109 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/harness/envelopes/result_envelope.json +14 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/harness/envelopes/task_envelope.json +20 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/harness/runner.py +303 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/telemetry/logger.py +112 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/README.md +18 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/config/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/gates/README.md +12 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/gates/check_env.sh +23 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/gates/check_paths.sh +20 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/gates/check_platform.sh +23 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/harness/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/harness/envelopes/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/installer/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/installer/install.sh +125 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/telemetry/README.md +11 -0
- package/.agents/skills/pr-ops/README.md +3 -0
- package/.agents/skills/pr-ops/SKILL.md +109 -0
- package/.agents/skills/ratatoskr-a2a/README.md +3 -0
- package/.agents/skills/ratatoskr-a2a/SKILL.md +148 -0
- package/.agents/skills/rules-check-drift/SKILL.md +81 -0
- package/.agents/skills/saga-bearings/README.md +3 -0
- package/.agents/skills/saga-bearings/SKILL.md +26 -0
- package/.agents/skills/saga-bearings/assets/bearings.md +161 -0
- package/.agents/skills/saga-bearings/assets/board-template.html +731 -0
- package/.agents/skills/saga-bearings/assets/recap.md +56 -0
- package/.agents/skills/syn-recovery/README.md +3 -0
- package/.agents/skills/syn-recovery/SKILL.md +54 -0
- package/.agents/skills/tyr-check/README.md +3 -0
- package/.agents/skills/tyr-check/SKILL.md +218 -0
- package/.agents/skills/urdh-hold/README.md +3 -0
- package/.agents/skills/urdh-hold/SKILL.md +25 -0
- package/.agents/skills/urdh-hold/assets/decisions.md +15 -0
- package/.agents/skills/urdh-hold/assets/hold.md +54 -0
- package/.agents/skills/vor-diagnostics/README.md +3 -0
- package/.agents/skills/vor-diagnostics/SKILL.md +68 -0
- package/.agents/skills/ymir-host/README.md +3 -0
- package/.agents/skills/ymir-host/SKILL.md +35 -0
- package/.agents/skills/ymir-host/assets/desktop.md +36 -0
- package/.agents/skills/ymir-host/assets/install.md +69 -0
- package/.agents/skills/ymir-host/assets/omarchy.md +297 -0
- package/.agents/skills/ymir-host/assets/runbooks.md +15 -0
- package/.agents/skills/ymir-host/assets/thjazi.md +220 -0
- package/.agents/skills/ymir-host/assets/update.md +64 -0
- package/.agents/tests/assets/board-render-harness.mjs +117 -0
- package/.agents/tests/cmux-test-safety.sh +51 -0
- package/.agents/tests/fixtures.sh +291 -0
- package/.agents/tests/fm-afk-inject-e2e.test.sh +428 -0
- package/.agents/tests/fm-afk-inject-herdr-e2e.test.sh +536 -0
- package/.agents/tests/fm-afk-launch.test.sh +961 -0
- package/.agents/tests/fm-afk-pi-herdr-return-e2e.test.sh +297 -0
- package/.agents/tests/fm-afk-return.test.sh +283 -0
- package/.agents/tests/fm-arm-pretool-check.test.sh +482 -0
- package/.agents/tests/fm-ask-user-authority.test.sh +42 -0
- package/.agents/tests/fm-backend-autodetect-smoke.test.sh +176 -0
- package/.agents/tests/fm-backend-cmux-smoke.test.sh +188 -0
- package/.agents/tests/fm-backend-cmux.test.sh +1166 -0
- package/.agents/tests/fm-backend-herdr-eventwait-smoke.test.sh +136 -0
- package/.agents/tests/fm-backend-herdr-eventwait.test.py +106 -0
- package/.agents/tests/fm-backend-herdr-focus-flash-e2e.test.sh +409 -0
- package/.agents/tests/fm-backend-herdr-launcher-workspace-e2e.test.sh +437 -0
- package/.agents/tests/fm-backend-herdr-presentation-e2e.test.sh +1424 -0
- package/.agents/tests/fm-backend-herdr-prune-safety-e2e.test.sh +180 -0
- package/.agents/tests/fm-backend-herdr-respawn-idem-e2e.test.sh +182 -0
- package/.agents/tests/fm-backend-herdr-smoke.test.sh +355 -0
- package/.agents/tests/fm-backend-herdr-workspace-per-home-e2e.test.sh +251 -0
- package/.agents/tests/fm-backend-herdr.test.sh +4606 -0
- package/.agents/tests/fm-backend-orca.test.sh +1357 -0
- package/.agents/tests/fm-backend-tmux-smoke.test.sh +173 -0
- package/.agents/tests/fm-backend-zellij-smoke.test.sh +205 -0
- package/.agents/tests/fm-backend-zellij.test.sh +1360 -0
- package/.agents/tests/fm-backend.test.sh +1142 -0
- package/.agents/tests/fm-backlog-atomicity.test.sh +2302 -0
- package/.agents/tests/fm-backlog-handoff.test.sh +1360 -0
- package/.agents/tests/fm-bearings-board-render.test.sh +135 -0
- package/.agents/tests/fm-bearings-board.test.sh +414 -0
- package/.agents/tests/fm-bearings-snapshot.test.sh +1990 -0
- package/.agents/tests/fm-bootstrap-network-parallel.test.sh +316 -0
- package/.agents/tests/fm-bootstrap.test.sh +1178 -0
- package/.agents/tests/fm-branch-supervision.test.sh +552 -0
- package/.agents/tests/fm-brief.test.sh +785 -0
- package/.agents/tests/fm-busy-adapter-wiring.test.sh +324 -0
- package/.agents/tests/fm-busy-state.test.sh +465 -0
- package/.agents/tests/fm-calm-pi-extension.test.sh +3979 -0
- package/.agents/tests/fm-captain-hold-lifecycle.test.sh +1187 -0
- package/.agents/tests/fm-cd-pretool-check.test.sh +400 -0
- package/.agents/tests/fm-check-unregister.test.sh +198 -0
- package/.agents/tests/fm-classify-corr-token.test.sh +543 -0
- package/.agents/tests/fm-classify-decision-key.test.sh +340 -0
- package/.agents/tests/fm-claude-stop-autoarm-live-e2e.test.sh +164 -0
- package/.agents/tests/fm-claude-stop-autoarm.test.sh +1190 -0
- package/.agents/tests/fm-cmux-claude-composer-live-e2e.test.sh +110 -0
- package/.agents/tests/fm-codex-continuity-live-e2e.test.sh +55 -0
- package/.agents/tests/fm-composer-ghost.test.sh +716 -0
- package/.agents/tests/fm-composer-lib.test.sh +666 -0
- package/.agents/tests/fm-composer-matrix-live-e2e.test.sh +220 -0
- package/.agents/tests/fm-control-herdr-smoke.test.sh +149 -0
- package/.agents/tests/fm-control-relaunch.test.sh +1530 -0
- package/.agents/tests/fm-control.test.sh +910 -0
- package/.agents/tests/fm-crew-state.test.sh +1610 -0
- package/.agents/tests/fm-cursor-harness.test.sh +404 -0
- package/.agents/tests/fm-cursor-primary-live-e2e.test.sh +217 -0
- package/.agents/tests/fm-cursor-primary.test.sh +708 -0
- package/.agents/tests/fm-daemon.test.sh +2740 -0
- package/.agents/tests/fm-documentation-audiences.test.sh +141 -0
- package/.agents/tests/fm-ensure-agents-md.test.sh +371 -0
- package/.agents/tests/fm-extension-binding.test.sh +2187 -0
- package/.agents/tests/fm-fleet-snapshot-view.test.sh +816 -0
- package/.agents/tests/fm-fleet-sync.test.sh +721 -0
- package/.agents/tests/fm-gate-refuse.test.sh +356 -0
- package/.agents/tests/fm-gitignore-config.test.sh +89 -0
- package/.agents/tests/fm-gotmp.test.sh +230 -0
- package/.agents/tests/fm-grok-continuity-live-e2e.test.sh +112 -0
- package/.agents/tests/fm-grok-harness.test.sh +117 -0
- package/.agents/tests/fm-grok-stop-live-e2e.test.sh +219 -0
- package/.agents/tests/fm-guard-stale-banner.test.sh +709 -0
- package/.agents/tests/fm-harness-adapter-instructions-live-e2e.test.sh +134 -0
- package/.agents/tests/fm-harness-adapter-references.test.sh +30 -0
- package/.agents/tests/fm-harness-liveness-drift-live-e2e.test.sh +151 -0
- package/.agents/tests/fm-herdr-lab.test.sh +243 -0
- package/.agents/tests/fm-herdr-session-cleanup-e2e.test.sh +146 -0
- package/.agents/tests/fm-herdr-session-cleanup.test.sh +329 -0
- package/.agents/tests/fm-herdr-submit-confirm-live-e2e.test.sh +125 -0
- package/.agents/tests/fm-herdr-version-floor-live-e2e.test.sh +144 -0
- package/.agents/tests/fm-home-summary-refresh.test.sh +971 -0
- package/.agents/tests/fm-inactive-reconcile.test.sh +485 -0
- package/.agents/tests/fm-kimi-harness.test.sh +687 -0
- package/.agents/tests/fm-lint-workflows.test.sh +532 -0
- package/.agents/tests/fm-lint.test.sh +1023 -0
- package/.agents/tests/fm-muse-harness.test.sh +932 -0
- package/.agents/tests/fm-muse-signals-live-e2e.test.sh +205 -0
- package/.agents/tests/fm-no-mistakes-required.test.sh +72 -0
- package/.agents/tests/fm-on.test.sh +507 -0
- package/.agents/tests/fm-opencode-primary-live-e2e.test.sh +357 -0
- package/.agents/tests/fm-operational-input.test.sh +160 -0
- package/.agents/tests/fm-peek-remote.test.sh +110 -0
- package/.agents/tests/fm-pending-reply.test.sh +1288 -0
- package/.agents/tests/fm-pi-branch-extension.test.sh +3182 -0
- package/.agents/tests/fm-pi-branch-live-e2e.test.sh +527 -0
- package/.agents/tests/fm-pi-primary-live-e2e.test.sh +345 -0
- package/.agents/tests/fm-pi-primary-types.test.sh +68 -0
- package/.agents/tests/fm-pi-watch-extension.test.sh +2843 -0
- package/.agents/tests/fm-pr-check-security.test.sh +2140 -0
- package/.agents/tests/fm-pr-merge.test.sh +2135 -0
- package/.agents/tests/fm-procevent-quota.test.sh +225 -0
- package/.agents/tests/fm-procevent-when.test.sh +406 -0
- package/.agents/tests/fm-procevent.test.sh +1745 -0
- package/.agents/tests/fm-project-origin.test.sh +110 -0
- package/.agents/tests/fm-public-followup.test.sh +2272 -0
- package/.agents/tests/fm-quota-array-dispatch-live-e2e.test.sh +526 -0
- package/.agents/tests/fm-quota-choose.test.sh +626 -0
- package/.agents/tests/fm-remote-backlog-handoff.test.sh +453 -0
- package/.agents/tests/fm-remote-doctor.test.sh +625 -0
- package/.agents/tests/fm-remote-entrypoint.test.sh +59 -0
- package/.agents/tests/fm-remote-job-orphan-reap.test.sh +205 -0
- package/.agents/tests/fm-remote-job.test.sh +768 -0
- package/.agents/tests/fm-remote-reply.test.sh +520 -0
- package/.agents/tests/fm-remote-secondmate-lifecycle-e2e.test.sh +1256 -0
- package/.agents/tests/fm-remote-secondmate-parent-binding.test.sh +326 -0
- package/.agents/tests/fm-remote-secondmate-trace-context.test.sh +310 -0
- package/.agents/tests/fm-remote-transport-lanes.test.sh +431 -0
- package/.agents/tests/fm-review-diff.test.sh +176 -0
- package/.agents/tests/fm-secondmate-harness.test.sh +2600 -0
- package/.agents/tests/fm-secondmate-lifecycle-e2e.test.sh +259 -0
- package/.agents/tests/fm-secondmate-liveness.test.sh +559 -0
- package/.agents/tests/fm-secondmate-reconcile.test.sh +732 -0
- package/.agents/tests/fm-secondmate-safety.test.sh +2972 -0
- package/.agents/tests/fm-secondmate-sync.test.sh +913 -0
- package/.agents/tests/fm-send-inbox-doorbell-live-e2e.test.sh +206 -0
- package/.agents/tests/fm-send-inbox.test.sh +352 -0
- package/.agents/tests/fm-send-popup-settle.test.sh +167 -0
- package/.agents/tests/fm-send-remote-delivery.test.sh +796 -0
- package/.agents/tests/fm-send-resolve-key.test.sh +551 -0
- package/.agents/tests/fm-send-secondmate-marker-herdr-e2e.test.sh +187 -0
- package/.agents/tests/fm-send-secondmate-marker.test.sh +278 -0
- package/.agents/tests/fm-send-settle.test.sh +147 -0
- package/.agents/tests/fm-send-strict.test.sh +241 -0
- package/.agents/tests/fm-session-lock-ancestry.test.sh +365 -0
- package/.agents/tests/fm-session-start.test.sh +2515 -0
- package/.agents/tests/fm-sessionstart-hook-live-e2e.test.sh +631 -0
- package/.agents/tests/fm-sessionstart-instruction-refresh-live-e2e.test.sh +230 -0
- package/.agents/tests/fm-sessionstart-nudge.test.sh +1039 -0
- package/.agents/tests/fm-shared-captain-inheritance.test.sh +404 -0
- package/.agents/tests/fm-spawn-batch.test.sh +148 -0
- package/.agents/tests/fm-spawn-dispatch-profile.test.sh +827 -0
- package/.agents/tests/fm-spawn-pool-base-freshen.test.sh +440 -0
- package/.agents/tests/fm-spawn-worktree-settle.test.sh +147 -0
- package/.agents/tests/fm-startup-memory-budget.test.sh +333 -0
- package/.agents/tests/fm-startup-network.test.sh +712 -0
- package/.agents/tests/fm-stow-cascade.test.sh +370 -0
- package/.agents/tests/fm-subagent-pretool-check.test.sh +291 -0
- package/.agents/tests/fm-supervision-events.test.sh +156 -0
- package/.agents/tests/fm-supervision-instructions.test.sh +189 -0
- package/.agents/tests/fm-tangle-guard.test.sh +277 -0
- package/.agents/tests/fm-task-delivery.test.sh +420 -0
- package/.agents/tests/fm-task-inbox.test.sh +513 -0
- package/.agents/tests/fm-teardown-endpoint-safety.test.sh +374 -0
- package/.agents/tests/fm-teardown.test.sh +2665 -0
- package/.agents/tests/fm-test-fixture-cleanup.test.sh +172 -0
- package/.agents/tests/fm-test-fixtures.test.sh +132 -0
- package/.agents/tests/fm-test-isolation-proof.test.sh +278 -0
- package/.agents/tests/fm-test-run.test.sh +1196 -0
- package/.agents/tests/fm-tmux-agent-liveness.test.sh +354 -0
- package/.agents/tests/fm-tmux-submit-busy.test.sh +340 -0
- package/.agents/tests/fm-tool-update-check.test.sh +1044 -0
- package/.agents/tests/fm-trace-context-lib.test.sh +253 -0
- package/.agents/tests/fm-trace-context-spawn.test.sh +581 -0
- package/.agents/tests/fm-transition-lib.test.sh +54 -0
- package/.agents/tests/fm-turnend-guard.test.sh +1822 -0
- package/.agents/tests/fm-update.test.sh +304 -0
- package/.agents/tests/fm-vendor-auth-probe.test.sh +395 -0
- package/.agents/tests/fm-voice-relay.test.sh +4741 -0
- package/.agents/tests/fm-wake-daemon-lifecycle-e2e.test.sh +171 -0
- package/.agents/tests/fm-wake-drain-open-decisions-cursor.test.sh +356 -0
- package/.agents/tests/fm-wake-drain-open-decisions.test.sh +226 -0
- package/.agents/tests/fm-wake-drain-unread-status.test.sh +379 -0
- package/.agents/tests/fm-wake-queue.test.sh +1224 -0
- package/.agents/tests/fm-watch-arm.test.sh +821 -0
- package/.agents/tests/fm-watch-checkpoint.test.sh +87 -0
- package/.agents/tests/fm-watch-recovery-loop.test.sh +223 -0
- package/.agents/tests/fm-watch-triage.test.sh +3889 -0
- package/.agents/tests/fm-watcher-lock.test.sh +1133 -0
- package/.agents/tests/fm-x-mode.test.sh +3042 -0
- package/.agents/tests/gleipnir-guard-pretool-check.test.sh +51 -0
- package/.agents/tests/gleipnir-machine-lock.test.sh +130 -0
- package/.agents/tests/herdr-test-safety.sh +42 -0
- package/.agents/tests/lib.sh +315 -0
- package/.agents/tests/remote-herdr-fixture.sh +125 -0
- package/.agents/tests/secondmate-helpers.sh +193 -0
- package/.agents/tests/smoke.test.sh +93 -0
- package/.agents/tests/wake-helpers.sh +338 -0
- package/.agents/tests/zellij-test-safety.sh +60 -0
- package/.agents/tools/README.md +10 -0
- package/.agents/tools/bin/tasks-cli +267 -0
- package/.agents/tools/tasks-cli.ts +216 -0
- package/AGENTS.md +498 -0
- package/CHANGELOG.md +1913 -0
- package/LICENSE +1 -1
- package/NOTICE +63 -0
- package/README.md +114 -60
- package/RULES/01-domains.md +51 -0
- package/RULES/02-agents.md +78 -0
- package/RULES/03-houses.md +61 -0
- package/RULES/04-hoard.md +97 -0
- package/RULES/05-platforms.md +67 -0
- package/RULES/06-append-only.md +108 -0
- package/RULES/07-config.md +101 -0
- package/RULES/08-delivery-gate.md +75 -0
- package/RULES/09-electron.md +58 -0
- package/RULES/README.md +22 -0
- package/bin/README.md +107 -0
- package/bin/a2a-mcp.sh +133 -0
- package/bin/a2a-serve.py +103 -0
- package/bin/a2a-serve.sh +8 -0
- package/bin/a2a-talk.sh +50 -0
- package/bin/a2abridge-ensure.sh +108 -0
- package/bin/agent-run.sh +43 -0
- package/bin/agents-config.sh +256 -0
- package/bin/apodex-smoke-test.sh +105 -0
- package/bin/bifrost-bridge.sh +131 -0
- package/bin/bifrost-ingress.sh +77 -0
- package/bin/bootstrap-macos.sh +112 -0
- package/bin/bootstrap-windows.ps1 +112 -0
- package/bin/branch-guard.sh +64 -0
- package/bin/brokk +73 -0
- package/bin/brokk-classify-lib.sh +1770 -0
- package/bin/brokk-lease-lib.sh +222 -0
- package/bin/brokk-lease.sh +193 -0
- package/bin/brokk-lint.sh +65 -0
- package/bin/brokk-send.sh +51 -0
- package/bin/brokk-update.sh +9 -0
- package/bin/brokk-wake-grant.sh +127 -0
- package/bin/brokk-wake-lib.sh +1849 -0
- package/bin/changelog-assemble.sh +154 -0
- package/bin/changelog-guard.sh +197 -0
- package/bin/crash-sense.sh +173 -0
- package/bin/design-check.sh +80 -0
- package/bin/design-icon.sh +153 -0
- package/bin/desktop-place.sh +224 -0
- package/bin/docs-guard.sh +39 -0
- package/bin/editor-place.sh +225 -0
- package/bin/eindri-acclaim.sh +47 -0
- package/bin/eindri-control.sh +28 -0
- package/bin/eindri-role.sh +83 -0
- package/bin/eindri-seat.sh +83 -0
- package/bin/eindri-seen.sh +54 -0
- package/bin/eindri-send.sh +15 -0
- package/bin/eindri-start.sh +98 -0
- package/bin/eindri-watch.sh +57 -0
- package/bin/einherjar-spawn.sh +576 -0
- package/bin/eir-doctor.sh +158 -0
- package/bin/erindi-brief.sh +271 -0
- package/bin/feature-inventory.sh +73 -0
- package/bin/fleet-apply.sh +81 -0
- package/bin/github-deploy.sh +94 -0
- package/bin/gjallarhorn-expose.sh +136 -0
- package/bin/gjallarhorn-notify.sh +71 -0
- package/bin/gjallarhorn-purge.sh +67 -0
- package/bin/gjallarhorn-tunnel.sh +85 -0
- package/bin/gleipnir-lock-lib.sh +284 -0
- package/bin/groa-update.sh +130 -0
- package/bin/hall-snapshot.sh +111 -0
- package/bin/hamr-harness.sh +246 -0
- package/bin/heimdall-ssh-keys.sh +374 -0
- package/bin/herdr-agents.py +44 -0
- package/bin/herdr-ensure.sh +104 -0
- package/bin/herdr-run.sh +452 -0
- package/bin/hermes-ensure.sh +88 -0
- package/bin/hlidskjalf-agents.sh +172 -0
- package/bin/hlidskjalf-usage.sh +196 -0
- package/bin/hoard-guard.sh +135 -0
- package/bin/hoard-lib.sh +105 -0
- package/bin/hodd.sh +102 -0
- package/bin/host-sense.sh +199 -0
- package/bin/huginn-research-worker.sh +121 -0
- package/bin/local-model-lock.sh +70 -0
- package/bin/mimir-bridge.py +259 -0
- package/bin/mimir-bridge.sh +100 -0
- package/bin/mimir-ingest.sh +131 -0
- package/bin/mimir-reflect.sh +27 -0
- package/bin/mimir.sh +113 -0
- package/bin/mjollnir-webhook.sh +72 -0
- package/bin/mjollnir.sh +104 -0
- package/bin/model-hardware.sh +96 -0
- package/bin/model-resolve.sh +160 -0
- package/bin/models-detect.sh +178 -0
- package/bin/nornir-cron-start.sh +162 -0
- package/bin/nornir-job-daily-briefing.sh +191 -0
- package/bin/nornir-job-git-sync.sh +152 -0
- package/bin/nornir-job-hall-snapshot.sh +28 -0
- package/bin/nornir-job-memory-housekeeping.sh +114 -0
- package/bin/nornir-job-nsr-compliance.sh +54 -0
- package/bin/nornir-job-observer.sh +166 -0
- package/bin/nornir-job-skillopt-sleep.sh +76 -0
- package/bin/npm-publish.sh +136 -0
- package/bin/omarchy-hook-install.sh +60 -0
- package/bin/omarchy-install.sh +161 -0
- package/bin/omarchy-plugins.sh +187 -0
- package/bin/omarchy-sense.sh +162 -0
- package/bin/perm-guard.sh +30 -0
- package/bin/pi-agent.sh +68 -0
- package/bin/pi-ensure.sh +77 -0
- package/bin/pi-local.sh +37 -0
- package/bin/pi-model-agnostic.sh +71 -0
- package/bin/pi-seat.sh +63 -0
- package/bin/prereq-ensure.sh +166 -0
- package/bin/private-guard.sh +58 -0
- package/bin/project-git.sh +69 -0
- package/bin/public-guard.sh +71 -0
- package/bin/ratatoskr.sh +49 -0
- package/bin/realm-lib.sh +32 -0
- package/bin/repo-scrub.sh +62 -0
- package/bin/rodd-operational-input.sh +250 -0
- package/bin/runes-append.sh +198 -0
- package/bin/saga-session-start.sh +172 -0
- package/bin/saga-sessionstart-run.sh +79 -0
- package/bin/saga-wake-drain.sh +41 -0
- package/bin/secret-guard.sh +63 -0
- package/bin/sessrumnir-ensure.sh +100 -0
- package/bin/sessrumnir-sync.sh +237 -0
- package/bin/sessrumnir.sh +104 -0
- package/bin/skillopt-setup.sh +76 -0
- package/bin/skuld-branch-outcome.sh +203 -0
- package/bin/skuld-branch-prompt.sh +101 -0
- package/bin/smidja-bootstrap.sh +94 -0
- package/bin/smidja-observe.sh +86 -0
- package/bin/syn-arm-pretool-check.sh +57 -0
- package/bin/syn-asset-pretool-check.sh +89 -0
- package/bin/syn-cd-pretool-check.sh +28 -0
- package/bin/syn-guard-pretool-check.sh +83 -0
- package/bin/syn-spawn-pretool-check.sh +58 -0
- package/bin/syn-turnend-guard.sh +36 -0
- package/bin/syn-watch-arm.sh +99 -0
- package/bin/tailscale-sync.sh +203 -0
- package/bin/telegram-bot.sh +82 -0
- package/bin/toolchain.sh +74 -0
- package/bin/ui-truth-check.sh +75 -0
- package/bin/utgard.sh +111 -0
- package/bin/valhalla.sh +115 -0
- package/bin/valknut-load.sh +298 -0
- package/bin/vor-crew-state.sh +124 -0
- package/bin/wedge-notify.sh +60 -0
- package/bin/workspace-provision.sh +80 -0
- package/bin/workspace-rag.sh +163 -0
- package/bin/wyrd-db.sh +47 -0
- package/bin/yggdrasil.sh +152 -0
- package/bin/ymir-edit.sh +145 -0
- package/bin/ymir-install.sh +806 -0
- package/bin/ymir-invite.sh +93 -0
- package/bin/ymir-isolation.sh +88 -0
- package/bin/ymir-migrate.sh +61 -0
- package/bin/ymir-plan.sh +356 -0
- package/bin/ymir-platform.sh +348 -0
- package/bin/ymir-say.sh +110 -0
- package/bin/ymir-setup-auth.sh +119 -0
- package/bin/ymir-validate.sh +193 -0
- package/bin/ymir.js +74 -16
- package/docs/Architecture.md +339 -0
- package/docs/design.md +351 -0
- package/docs/installations/README.md +63 -0
- package/docs/installations/ymir-home.md +93 -0
- package/docs/integration.md +105 -0
- package/docs/lore.md +1060 -0
- package/docs/research/agent-harnesses.md +290 -0
- package/docs/runbooks/README.md +19 -0
- package/docs/runbooks/a2a.md +91 -0
- package/docs/runbooks/agent-permissions.md +99 -0
- package/docs/runbooks/agents.md +57 -0
- package/docs/runbooks/models.md +69 -0
- package/docs/runbooks/realm-onboarding.md +60 -0
- package/docs/runbooks/secrets-and-hoard.md +60 -0
- package/docs/runbooks/updates-and-migrations.md +110 -0
- package/docs/runbooks/worktrees-isolation.md +72 -0
- package/docs/session-start.md +105 -0
- package/docs/skillopt-integration.md +321 -0
- package/docs/sync-system.md +66 -0
- package/docs/workspaces.md +104 -0
- package/docs/ymir-rut.md +260 -0
- package/package.json +54 -14
- package/packaging/build.sh +74 -0
- package/packaging/macos/Ymir Installer.command +43 -0
- package/packaging/windows/ymir-setup.nsi +74 -0
- package/scripts/README.md +22 -0
- package/scripts/electron.sh +269 -0
- package/scripts/lower.sh +34 -0
- package/scripts/raise.sh +42 -0
- package/scripts/start.sh +217 -0
- package/scripts/stop.sh +113 -0
- package/install.sh +0 -35
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Regression tests for fm-spawn's pooled-worktree base refresh.
|
|
3
|
+
#
|
|
4
|
+
# A treehouse pool can return a clean detached worktree whose origin/main was
|
|
5
|
+
# advanced after the worktree was allocated.
|
|
6
|
+
# These tests drive the real spawn path with a fake terminal, then prove it
|
|
7
|
+
# starts the worker from the fetched origin/main tip or stops when origin is
|
|
8
|
+
# unreachable.
|
|
9
|
+
set -u
|
|
10
|
+
|
|
11
|
+
# shellcheck source=tests/fixtures.sh
|
|
12
|
+
. "$(dirname "${BASH_SOURCE[0]}")/fixtures.sh"
|
|
13
|
+
|
|
14
|
+
TMP_ROOT=$(fm_test_tmproot fm-spawn-pool-base-freshen)
|
|
15
|
+
|
|
16
|
+
make_case() {
|
|
17
|
+
local name=$1 id=$2 default=${3:-main} case_dir home project origin pool publisher fakebin initial
|
|
18
|
+
case_dir="$TMP_ROOT/$name"
|
|
19
|
+
home="$case_dir/home"
|
|
20
|
+
project="$case_dir/project"
|
|
21
|
+
origin="$case_dir/origin.git"
|
|
22
|
+
pool="$case_dir/pool"
|
|
23
|
+
publisher="$case_dir/publisher"
|
|
24
|
+
fakebin=$(make_spawn_fakebin "$case_dir/fake")
|
|
25
|
+
|
|
26
|
+
mkdir -p "$home/data/$id" "$home/projects" "$home/state" "$home/config"
|
|
27
|
+
printf 'codex\n' > "$home/config/crew-harness"
|
|
28
|
+
printf 'brief for %s\n' "$id" > "$home/data/$id/brief.md"
|
|
29
|
+
touch "$home/state/.last-watcher-beat"
|
|
30
|
+
|
|
31
|
+
git init --quiet -b "$default" "$project"
|
|
32
|
+
printf 'base\n' > "$project/README.md"
|
|
33
|
+
git -C "$project" add README.md
|
|
34
|
+
git -C "$project" -c user.name='Firstmate Tests' -c user.email='tests@example.invalid' commit -qm initial
|
|
35
|
+
git clone --quiet --bare "$project" "$origin"
|
|
36
|
+
git -C "$project" remote add origin "file://$origin"
|
|
37
|
+
initial=$(git -C "$project" rev-parse HEAD)
|
|
38
|
+
git -C "$project" worktree add --quiet --detach "$pool" "$initial"
|
|
39
|
+
|
|
40
|
+
git clone --quiet "file://$origin" "$publisher"
|
|
41
|
+
printf 'must survive a newly spawned branch\n' > "$publisher/advanced-main.txt"
|
|
42
|
+
git -C "$publisher" add advanced-main.txt
|
|
43
|
+
git -C "$publisher" -c user.name='Firstmate Tests' -c user.email='tests@example.invalid' commit -qm advance-main
|
|
44
|
+
git -C "$publisher" push --quiet origin "$default"
|
|
45
|
+
|
|
46
|
+
printf '%s\n' "$case_dir|$home|$project|$pool|$fakebin|$initial|$default"
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
read_case_record() {
|
|
50
|
+
IFS='|' read -r CASE_DIR HOME_DIR PROJECT_DIR POOL_DIR FAKEBIN_DIR INITIAL_SHA DEFAULT_BRANCH <<EOF
|
|
51
|
+
$1
|
|
52
|
+
EOF
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
run_spawn() {
|
|
56
|
+
local id=$1
|
|
57
|
+
shift
|
|
58
|
+
fm_test_run_spawn "$HOME_DIR" "$POOL_DIR" "$FAKEBIN_DIR" \
|
|
59
|
+
"$id" "$PROJECT_DIR" "$@"
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
test_stale_pool_base_refreshes_before_branching() {
|
|
63
|
+
local rec id out status current branch_head
|
|
64
|
+
id='pool-current-base-r1'
|
|
65
|
+
rec=$(make_case current-base "$id")
|
|
66
|
+
read_case_record "$rec"
|
|
67
|
+
|
|
68
|
+
out=$(run_spawn "$id" --mode no-mistakes --yolo off)
|
|
69
|
+
status=$?
|
|
70
|
+
expect_code 0 "$status" "spawn should refresh a stale pooled worktree"
|
|
71
|
+
assert_contains "$out" "spawned $id" "spawn did not report success"
|
|
72
|
+
current=$(git -C "$POOL_DIR" rev-parse origin/main)
|
|
73
|
+
branch_head=$(git -C "$POOL_DIR" rev-parse HEAD)
|
|
74
|
+
[ "$branch_head" = "$current" ] || fail "spawn left the pooled worktree on stale history"
|
|
75
|
+
[ "$branch_head" != "$INITIAL_SHA" ] || fail "fixture did not prove origin/main advanced past the pool base"
|
|
76
|
+
if [ "${FM_TEST_EVIDENCE:-0}" = 1 ]; then
|
|
77
|
+
printf '# observed spawn: %s\n' "$(printf '%s\n' "$out" | tail -n 1)"
|
|
78
|
+
printf '# observed base: HEAD=%s origin/main=%s advanced-main=%s\n' \
|
|
79
|
+
"$branch_head" "$current" "$(cat "$POOL_DIR/advanced-main.txt")"
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
id='pool-current-base-repeat-r1'
|
|
83
|
+
mkdir -p "$HOME_DIR/data/$id"
|
|
84
|
+
printf 'brief for %s\n' "$id" > "$HOME_DIR/data/$id/brief.md"
|
|
85
|
+
out=$(run_spawn "$id" --mode no-mistakes --yolo off)
|
|
86
|
+
status=$?
|
|
87
|
+
expect_code 0 "$status" "repeating the base refresh should be idempotent"
|
|
88
|
+
[ "$(git -C "$POOL_DIR" rev-parse HEAD)" = "$current" ] \
|
|
89
|
+
|| fail "an idempotent repeat moved the pool away from current origin/main"
|
|
90
|
+
|
|
91
|
+
git -C "$POOL_DIR" checkout --quiet -b "fm/$id"
|
|
92
|
+
git -C "$POOL_DIR" diff --exit-code origin/main...HEAD >/dev/null \
|
|
93
|
+
|| fail "a branch created after spawn differs from current origin/main"
|
|
94
|
+
assert_grep 'must survive a newly spawned branch' "$POOL_DIR/advanced-main.txt" \
|
|
95
|
+
"the branch created after spawn omitted advanced-main content"
|
|
96
|
+
pass "a stale pooled worktree refreshes to current origin/main before a crew branch is created"
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
test_non_main_default_branch_refreshes_before_branching() {
|
|
100
|
+
local rec id out status current branch_head
|
|
101
|
+
id='pool-current-trunk-r2'
|
|
102
|
+
rec=$(make_case current-trunk "$id" trunk)
|
|
103
|
+
read_case_record "$rec"
|
|
104
|
+
|
|
105
|
+
out=$(run_spawn "$id" --mode no-mistakes --yolo off)
|
|
106
|
+
status=$?
|
|
107
|
+
expect_code 0 "$status" "spawn should refresh a stale pooled worktree on a non-main default branch"
|
|
108
|
+
current=$(git -C "$POOL_DIR" rev-parse "origin/$DEFAULT_BRANCH")
|
|
109
|
+
branch_head=$(git -C "$POOL_DIR" rev-parse HEAD)
|
|
110
|
+
[ "$branch_head" = "$current" ] || fail "spawn did not refresh to current origin/$DEFAULT_BRANCH"
|
|
111
|
+
[ "$branch_head" != "$INITIAL_SHA" ] || fail "fixture did not prove origin/$DEFAULT_BRANCH advanced past the pool base"
|
|
112
|
+
pass "a stale pooled worktree resolves and refreshes a non-main default branch"
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
test_unreachable_origin_refuses_stale_pool_base() {
|
|
116
|
+
local rec id out status before after
|
|
117
|
+
id='pool-unreachable-origin-r2'
|
|
118
|
+
rec=$(make_case unreachable-origin "$id")
|
|
119
|
+
read_case_record "$rec"
|
|
120
|
+
git -C "$POOL_DIR" remote set-url origin "file://$CASE_DIR/missing-origin.git"
|
|
121
|
+
before=$(git -C "$POOL_DIR" rev-parse HEAD)
|
|
122
|
+
|
|
123
|
+
out=$(run_spawn "$id" --mode no-mistakes --yolo off)
|
|
124
|
+
status=$?
|
|
125
|
+
[ "$status" -ne 0 ] || fail "spawn succeeded despite an unreachable origin"
|
|
126
|
+
assert_contains "$out" "could not fetch origin" \
|
|
127
|
+
"spawn did not clearly refuse an unreachable origin"
|
|
128
|
+
after=$(git -C "$POOL_DIR" rev-parse HEAD)
|
|
129
|
+
[ "$after" = "$before" ] || fail "spawn changed the pooled worktree after origin became unreachable"
|
|
130
|
+
if [ "${FM_TEST_EVIDENCE:-0}" = 1 ]; then
|
|
131
|
+
printf '# observed unreachable-origin refusal: %s\n' "$(printf '%s\n' "$out" | tail -n 1)"
|
|
132
|
+
fi
|
|
133
|
+
pass "an unreachable origin refuses a potentially stale pooled worktree"
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
test_direct_pr_and_scout_refresh_before_launch() {
|
|
137
|
+
local rec id out status contract current
|
|
138
|
+
for contract in direct-pr scout; do
|
|
139
|
+
id="pool-${contract}-r3"
|
|
140
|
+
rec=$(make_case "$contract" "$id")
|
|
141
|
+
read_case_record "$rec"
|
|
142
|
+
if [ "$contract" = scout ]; then
|
|
143
|
+
out=$(run_spawn "$id" --scout)
|
|
144
|
+
else
|
|
145
|
+
out=$(run_spawn "$id" --mode direct-PR --yolo off)
|
|
146
|
+
fi
|
|
147
|
+
status=$?
|
|
148
|
+
expect_code 0 "$status" "$contract spawn should refresh a stale pooled worktree"
|
|
149
|
+
current=$(git -C "$POOL_DIR" rev-parse origin/main)
|
|
150
|
+
[ "$(git -C "$POOL_DIR" rev-parse HEAD)" = "$current" ] \
|
|
151
|
+
|| fail "$contract spawn did not start at current origin/main"
|
|
152
|
+
assert_grep 'must survive a newly spawned branch' "$POOL_DIR/advanced-main.txt" \
|
|
153
|
+
"$contract spawn omitted advanced-main content"
|
|
154
|
+
if [ "${FM_TEST_EVIDENCE:-0}" = 1 ]; then
|
|
155
|
+
printf '# observed %s spawn: %s\n' "$contract" "$(printf '%s\n' "$out" | tail -n 1)"
|
|
156
|
+
fi
|
|
157
|
+
done
|
|
158
|
+
pass "direct-PR ships and scouts both refresh stale pooled worktrees before launch"
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
test_dirty_pool_refuses_without_discarding_work() {
|
|
162
|
+
local rec id out status before
|
|
163
|
+
id='pool-dirty-refusal-r4'
|
|
164
|
+
rec=$(make_case dirty-refusal "$id")
|
|
165
|
+
read_case_record "$rec"
|
|
166
|
+
before=$(git -C "$POOL_DIR" rev-parse HEAD)
|
|
167
|
+
printf 'keep this local work\n' > "$POOL_DIR/uncommitted.txt"
|
|
168
|
+
|
|
169
|
+
out=$(run_spawn "$id" --mode no-mistakes --yolo off)
|
|
170
|
+
status=$?
|
|
171
|
+
[ "$status" -ne 0 ] || fail "spawn succeeded despite a dirty pooled worktree"
|
|
172
|
+
assert_contains "$out" "is not clean" "spawn did not clearly refuse a dirty pooled worktree"
|
|
173
|
+
[ "$(git -C "$POOL_DIR" rev-parse HEAD)" = "$before" ] \
|
|
174
|
+
|| fail "spawn moved HEAD while refusing a dirty pooled worktree"
|
|
175
|
+
assert_grep 'keep this local work' "$POOL_DIR/uncommitted.txt" \
|
|
176
|
+
"spawn discarded uncommitted work while refusing the pool"
|
|
177
|
+
if [ "${FM_TEST_EVIDENCE:-0}" = 1 ]; then
|
|
178
|
+
printf '# observed dirty refusal: %s; preserved=%s\n' \
|
|
179
|
+
"$(printf '%s\n' "$out" | tail -n 1)" "$(cat "$POOL_DIR/uncommitted.txt")"
|
|
180
|
+
fi
|
|
181
|
+
pass "a dirty pooled worktree is refused without discarding its local work"
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
test_unresolved_remote_default_refuses_pool() {
|
|
185
|
+
local rec id out status before
|
|
186
|
+
id='pool-unresolved-default-r5'
|
|
187
|
+
rec=$(make_case unresolved-default "$id")
|
|
188
|
+
read_case_record "$rec"
|
|
189
|
+
git --git-dir="$CASE_DIR/origin.git" symbolic-ref HEAD refs/heads/missing-default
|
|
190
|
+
before=$(git -C "$POOL_DIR" rev-parse HEAD)
|
|
191
|
+
|
|
192
|
+
out=$(run_spawn "$id" --mode no-mistakes --yolo off)
|
|
193
|
+
status=$?
|
|
194
|
+
[ "$status" -ne 0 ] || fail "spawn succeeded despite an unresolved remote default branch"
|
|
195
|
+
assert_contains "$out" "could not resolve origin's current default branch" \
|
|
196
|
+
"spawn did not clearly refuse an unresolved remote default branch"
|
|
197
|
+
[ "$(git -C "$POOL_DIR" rev-parse HEAD)" = "$before" ] \
|
|
198
|
+
|| fail "spawn moved HEAD after failing to resolve the remote default branch"
|
|
199
|
+
if [ "${FM_TEST_EVIDENCE:-0}" = 1 ]; then
|
|
200
|
+
printf '# observed unresolved-default refusal: %s\n' "$(printf '%s\n' "$out" | tail -n 1)"
|
|
201
|
+
fi
|
|
202
|
+
pass "an unresolved remote default branch refuses the pooled worktree"
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
# A slot left on a stale submodule pin is the field failure this diagnosis exists
|
|
206
|
+
# for: a refresh moved the superproject and left the submodule behind, so the
|
|
207
|
+
# refusal fires a spawn later, on a slot whose own `git status` looks clean to the
|
|
208
|
+
# operator. Nothing here is converged - the gate only has to say why. The fixture
|
|
209
|
+
# only builds the repositories; the residue itself is produced by a real spawn, so
|
|
210
|
+
# these tests cover the reset that actually strands the submodule.
|
|
211
|
+
make_submodule_case() { # <name> <id>
|
|
212
|
+
local name=$1 id=$2 case_dir home project origin pool publisher fakebin sub subpin1 subpin2 advanced
|
|
213
|
+
case_dir="$TMP_ROOT/$name"
|
|
214
|
+
home="$case_dir/home"
|
|
215
|
+
project="$case_dir/project"
|
|
216
|
+
origin="$case_dir/origin.git"
|
|
217
|
+
pool="$case_dir/pool"
|
|
218
|
+
publisher="$case_dir/publisher"
|
|
219
|
+
sub="$case_dir/sub-origin"
|
|
220
|
+
fakebin=$(make_spawn_fakebin "$case_dir/fake")
|
|
221
|
+
|
|
222
|
+
mkdir -p "$home/data/$id" "$home/projects" "$home/state" "$home/config"
|
|
223
|
+
printf 'codex\n' > "$home/config/crew-harness"
|
|
224
|
+
printf 'brief for %s\n' "$id" > "$home/data/$id/brief.md"
|
|
225
|
+
touch "$home/state/.last-watcher-beat"
|
|
226
|
+
|
|
227
|
+
git init --quiet -b main "$sub"
|
|
228
|
+
printf 'pin one\n' > "$sub/lib.txt"
|
|
229
|
+
git -C "$sub" add lib.txt
|
|
230
|
+
git -C "$sub" -c user.name='Firstmate Tests' -c user.email='tests@example.invalid' commit -qm sub-one
|
|
231
|
+
subpin1=$(git -C "$sub" rev-parse HEAD)
|
|
232
|
+
printf 'pin two\n' > "$sub/lib.txt"
|
|
233
|
+
git -C "$sub" -c user.name='Firstmate Tests' -c user.email='tests@example.invalid' commit -qam sub-two
|
|
234
|
+
subpin2=$(git -C "$sub" rev-parse HEAD)
|
|
235
|
+
git -C "$sub" checkout --quiet "$subpin1"
|
|
236
|
+
|
|
237
|
+
git init --quiet -b main "$project"
|
|
238
|
+
printf 'base\n' > "$project/README.md"
|
|
239
|
+
git -C "$project" add README.md
|
|
240
|
+
git -C "$project" -c protocol.file.allow=always -c user.name='Firstmate Tests' -c user.email='tests@example.invalid' \
|
|
241
|
+
submodule --quiet add "file://$sub" ui
|
|
242
|
+
git -C "$project" -c user.name='Firstmate Tests' -c user.email='tests@example.invalid' commit -qm initial
|
|
243
|
+
git clone --quiet --bare "$project" "$origin"
|
|
244
|
+
git -C "$project" remote add origin "file://$origin"
|
|
245
|
+
git -C "$project" worktree add --quiet --detach "$pool" HEAD
|
|
246
|
+
git -C "$pool" -c protocol.file.allow=always submodule --quiet update --init
|
|
247
|
+
|
|
248
|
+
# Advance origin and move the submodule pin, exactly as the field incident did.
|
|
249
|
+
git clone --quiet "file://$origin" "$publisher"
|
|
250
|
+
git -C "$publisher" -c protocol.file.allow=always submodule --quiet update --init
|
|
251
|
+
git -C "$publisher/ui" checkout --quiet "$subpin2"
|
|
252
|
+
git -C "$publisher" -c user.name='Firstmate Tests' -c user.email='tests@example.invalid' commit -qam advance-pin
|
|
253
|
+
git -C "$publisher" push --quiet origin main
|
|
254
|
+
advanced=$(git -C "$publisher" rev-parse HEAD)
|
|
255
|
+
|
|
256
|
+
printf '%s\n' "$case_dir|$home|$project|$pool|$fakebin|$subpin1|$subpin2|$advanced"
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
read_submodule_case() {
|
|
260
|
+
IFS='|' read -r CASE_DIR HOME_DIR PROJECT_DIR POOL_DIR FAKEBIN_DIR SUBPIN1 SUBPIN2 ADVANCED_SHA <<EOF
|
|
261
|
+
$1
|
|
262
|
+
EOF
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
# The first of two consecutive spawns: it succeeds, resets the superproject onto
|
|
266
|
+
# the base that moved the pin, and leaves the submodule checkout on the pin the
|
|
267
|
+
# old base recorded. That reset is what strands the slot, so every case below
|
|
268
|
+
# starts from residue this code path actually produced rather than a hand-built one.
|
|
269
|
+
strand_submodule_pin_via_spawn() { # <seed-id>
|
|
270
|
+
local id=$1 out status
|
|
271
|
+
mkdir -p "$HOME_DIR/data/$id"
|
|
272
|
+
printf 'brief for %s\n' "$id" > "$HOME_DIR/data/$id/brief.md"
|
|
273
|
+
out=$(run_spawn "$id" --mode no-mistakes --yolo off)
|
|
274
|
+
status=$?
|
|
275
|
+
expect_code 0 "$status" "the spawn that moves the submodule pin should succeed"
|
|
276
|
+
assert_contains "$out" "spawned $id" "the spawn that moves the submodule pin did not report success"
|
|
277
|
+
[ "$(git -C "$POOL_DIR" rev-parse HEAD)" = "$ADVANCED_SHA" ] \
|
|
278
|
+
|| fail "the first spawn did not move the pooled base across the moved submodule pin"
|
|
279
|
+
[ "$(git -C "$POOL_DIR/ui" rev-parse HEAD)" = "$SUBPIN1" ] \
|
|
280
|
+
|| fail "the first spawn did not strand the submodule on the pin the old base recorded"
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
test_stale_submodule_pin_explains_itself() {
|
|
284
|
+
local rec id out status before before_sub
|
|
285
|
+
id='pool-stale-pin-r7'
|
|
286
|
+
rec=$(make_submodule_case stale-pin "$id")
|
|
287
|
+
read_submodule_case "$rec"
|
|
288
|
+
strand_submodule_pin_via_spawn 'pool-stale-pin-seed-r7'
|
|
289
|
+
before=$(git -C "$POOL_DIR" rev-parse HEAD)
|
|
290
|
+
before_sub=$(git -C "$POOL_DIR/ui" rev-parse HEAD)
|
|
291
|
+
|
|
292
|
+
out=$(run_spawn "$id" --mode no-mistakes --yolo off)
|
|
293
|
+
status=$?
|
|
294
|
+
[ "$status" -ne 0 ] || fail "the second spawn launched from a slot carrying a stale submodule pin"
|
|
295
|
+
assert_contains "$out" "stale submodule checkout" \
|
|
296
|
+
"refusal did not name the cause as a stale submodule checkout"
|
|
297
|
+
assert_contains "$out" "submodule 'ui'" "refusal did not name the submodule"
|
|
298
|
+
assert_contains "$out" "$SUBPIN1" "refusal did not report the pin the slot actually has"
|
|
299
|
+
assert_contains "$out" "$SUBPIN2" "refusal did not report the pin the base records"
|
|
300
|
+
# No remedy is printed on purpose: the containment check reads local refs only,
|
|
301
|
+
# so a stale remote-tracking ref can make an unpushed commit look contained, and
|
|
302
|
+
# a checkout command on that judgement could cost the operator a commit.
|
|
303
|
+
assert_not_contains "$out" "submodule update --checkout" \
|
|
304
|
+
"refusal printed a remedy command the containment check cannot stand behind"
|
|
305
|
+
assert_not_contains "$out" "refusing to discard uncommitted work" \
|
|
306
|
+
"a stale pin was misreported as uncommitted work"
|
|
307
|
+
[ "$(git -C "$POOL_DIR" rev-parse HEAD)" = "$before" ] \
|
|
308
|
+
|| fail "spawn moved HEAD while refusing a stale submodule pin"
|
|
309
|
+
[ "$(git -C "$POOL_DIR/ui" rev-parse HEAD)" = "$before_sub" ] \
|
|
310
|
+
|| fail "spawn converged the submodule; this gate must never touch the slot"
|
|
311
|
+
if [ "${FM_TEST_EVIDENCE:-0}" = 1 ]; then
|
|
312
|
+
printf '# observed stale-pin refusal: %s\n' "$(printf '%s\n' "$out" | grep 'submodule' | head -n 1)"
|
|
313
|
+
fi
|
|
314
|
+
pass "two consecutive spawns across a moved submodule pin end in a refusal naming both pins and no remedy"
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
test_unpushed_submodule_commit_is_still_uncommitted_work() {
|
|
318
|
+
local rec id out status unpushed before before_sub
|
|
319
|
+
id='pool-sub-unpushed-r10'
|
|
320
|
+
rec=$(make_submodule_case sub-unpushed "$id")
|
|
321
|
+
read_submodule_case "$rec"
|
|
322
|
+
strand_submodule_pin_via_spawn 'pool-sub-unpushed-seed-r10'
|
|
323
|
+
# A commit made inside the submodule and never pushed leaves the submodule work
|
|
324
|
+
# tree clean and the pins different - the same two facts a stale pin shows. Any
|
|
325
|
+
# checkout of the recorded pin would move HEAD off this commit and leave it
|
|
326
|
+
# unreferenced, so this case must keep the conservative refusal.
|
|
327
|
+
printf 'unlanded submodule work\n' > "$POOL_DIR/ui/unlanded.txt"
|
|
328
|
+
git -C "$POOL_DIR/ui" add unlanded.txt
|
|
329
|
+
git -C "$POOL_DIR/ui" -c user.name='Firstmate Tests' -c user.email='tests@example.invalid' \
|
|
330
|
+
commit -qm unlanded-submodule-work
|
|
331
|
+
unpushed=$(git -C "$POOL_DIR/ui" rev-parse HEAD)
|
|
332
|
+
[ -z "$(git -C "$POOL_DIR/ui" status --porcelain)" ] \
|
|
333
|
+
|| fail "fixture did not leave the submodule work tree clean"
|
|
334
|
+
[ "$unpushed" != "$(git -C "$POOL_DIR" rev-parse "HEAD:ui")" ] \
|
|
335
|
+
|| fail "fixture did not leave the recorded pin different from what is checked out"
|
|
336
|
+
before=$(git -C "$POOL_DIR" rev-parse HEAD)
|
|
337
|
+
before_sub=$unpushed
|
|
338
|
+
|
|
339
|
+
out=$(run_spawn "$id" --mode no-mistakes --yolo off)
|
|
340
|
+
status=$?
|
|
341
|
+
[ "$status" -ne 0 ] || fail "spawn launched from a slot holding an unpushed submodule commit"
|
|
342
|
+
assert_contains "$out" "refusing to discard uncommitted work" \
|
|
343
|
+
"an unpushed submodule commit was not refused as uncommitted work"
|
|
344
|
+
assert_not_contains "$out" "stale submodule checkout" \
|
|
345
|
+
"an unpushed submodule commit was misreported as a stale pin"
|
|
346
|
+
assert_not_contains "$out" "is checked out at" \
|
|
347
|
+
"an unpushed submodule commit still drew the stale-pin diagnosis"
|
|
348
|
+
[ "$(git -C "$POOL_DIR/ui" rev-parse HEAD)" = "$before_sub" ] \
|
|
349
|
+
|| fail "spawn moved the submodule off its unpushed commit"
|
|
350
|
+
git -C "$POOL_DIR/ui" cat-file -e "$unpushed^{commit}" \
|
|
351
|
+
|| fail "the unpushed submodule commit did not survive the refusal"
|
|
352
|
+
assert_grep 'unlanded submodule work' "$POOL_DIR/ui/unlanded.txt" \
|
|
353
|
+
"spawn discarded the unpushed submodule work while refusing the pool"
|
|
354
|
+
[ "$(git -C "$POOL_DIR" rev-parse HEAD)" = "$before" ] \
|
|
355
|
+
|| fail "spawn moved HEAD while refusing a slot holding an unpushed submodule commit"
|
|
356
|
+
pass "an unpushed submodule commit keeps the uncommitted-work refusal and survives it"
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
test_work_inside_submodule_is_still_uncommitted_work() {
|
|
360
|
+
local rec id out status
|
|
361
|
+
id='pool-sub-work-r8'
|
|
362
|
+
rec=$(make_submodule_case sub-work "$id")
|
|
363
|
+
read_submodule_case "$rec"
|
|
364
|
+
strand_submodule_pin_via_spawn 'pool-sub-work-seed-r8'
|
|
365
|
+
# Put the submodule back on the pin the base records, so the ONLY deviation is
|
|
366
|
+
# real work inside it. This must never be softened into a stale-pin diagnosis.
|
|
367
|
+
git -C "$POOL_DIR/ui" checkout --quiet "$SUBPIN2"
|
|
368
|
+
printf 'work that must survive\n' > "$POOL_DIR/ui/keep-me.txt"
|
|
369
|
+
|
|
370
|
+
out=$(run_spawn "$id" --mode no-mistakes --yolo off)
|
|
371
|
+
status=$?
|
|
372
|
+
[ "$status" -ne 0 ] || fail "spawn launched from a slot holding work inside a submodule"
|
|
373
|
+
assert_contains "$out" "refusing to discard uncommitted work" \
|
|
374
|
+
"work inside a submodule was not refused as uncommitted work"
|
|
375
|
+
assert_not_contains "$out" "stale submodule checkout" \
|
|
376
|
+
"real work inside a submodule was misreported as a stale pin"
|
|
377
|
+
assert_grep 'work that must survive' "$POOL_DIR/ui/keep-me.txt" \
|
|
378
|
+
"spawn discarded work inside the submodule while refusing the pool"
|
|
379
|
+
pass "work inside a submodule is still refused as uncommitted work, not called stale"
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
test_stale_pin_carrying_real_work_is_not_called_stale() {
|
|
383
|
+
local rec id out status
|
|
384
|
+
id='pool-sub-both-r9'
|
|
385
|
+
rec=$(make_submodule_case sub-both "$id")
|
|
386
|
+
read_submodule_case "$rec"
|
|
387
|
+
strand_submodule_pin_via_spawn 'pool-sub-both-seed-r9'
|
|
388
|
+
# Stale pin AND real work inside it: calling this merely stale would be wrong, so
|
|
389
|
+
# the refusal must stay the conservative one.
|
|
390
|
+
printf 'work that must survive\n' > "$POOL_DIR/ui/keep-me.txt"
|
|
391
|
+
|
|
392
|
+
out=$(run_spawn "$id" --mode no-mistakes --yolo off)
|
|
393
|
+
status=$?
|
|
394
|
+
[ "$status" -ne 0 ] || fail "spawn launched from a slot with a stale pin and work inside it"
|
|
395
|
+
assert_contains "$out" "refusing to discard uncommitted work" \
|
|
396
|
+
"a stale pin carrying real work was not refused as uncommitted work"
|
|
397
|
+
assert_not_contains "$out" "stale submodule checkout" \
|
|
398
|
+
"a submodule holding real work was reported as merely stale"
|
|
399
|
+
assert_grep 'work that must survive' "$POOL_DIR/ui/keep-me.txt" \
|
|
400
|
+
"spawn discarded work inside the submodule while refusing the pool"
|
|
401
|
+
pass "a stale pin carrying real work is refused conservatively, never called stale"
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
test_stale_pin_beside_other_dirt_reports_one_verdict() {
|
|
405
|
+
local rec id out status
|
|
406
|
+
id='pool-sub-mixed-r11'
|
|
407
|
+
rec=$(make_submodule_case sub-mixed "$id")
|
|
408
|
+
read_submodule_case "$rec"
|
|
409
|
+
strand_submodule_pin_via_spawn 'pool-sub-mixed-seed-r11'
|
|
410
|
+
# Git sorts status paths, so the stale 'ui' entry is scanned before this file.
|
|
411
|
+
# The conservative verdict must not arrive contradicted by a stale-pin line.
|
|
412
|
+
printf 'notes the operator still wants\n' > "$POOL_DIR/zz-notes.txt"
|
|
413
|
+
|
|
414
|
+
out=$(run_spawn "$id" --mode no-mistakes --yolo off)
|
|
415
|
+
status=$?
|
|
416
|
+
[ "$status" -ne 0 ] || fail "spawn launched from a slot with a stale pin beside an untracked file"
|
|
417
|
+
assert_contains "$out" "refusing to discard uncommitted work" \
|
|
418
|
+
"a stale pin beside an untracked file was not refused as uncommitted work"
|
|
419
|
+
assert_not_contains "$out" "stale submodule checkout" \
|
|
420
|
+
"a slot carrying more than a stale pin was reported as merely stale"
|
|
421
|
+
assert_not_contains "$out" "is checked out at" \
|
|
422
|
+
"the stale-pin diagnosis was printed alongside the conservative refusal"
|
|
423
|
+
assert_grep 'notes the operator still wants' "$POOL_DIR/zz-notes.txt" \
|
|
424
|
+
"spawn discarded the untracked file while refusing the pool"
|
|
425
|
+
pass "a stale pin beside other dirt yields the conservative refusal alone, with no stale-pin line"
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
test_stale_pool_base_refreshes_before_branching
|
|
429
|
+
test_non_main_default_branch_refreshes_before_branching
|
|
430
|
+
test_direct_pr_and_scout_refresh_before_launch
|
|
431
|
+
test_dirty_pool_refuses_without_discarding_work
|
|
432
|
+
test_unresolved_remote_default_refuses_pool
|
|
433
|
+
test_unreachable_origin_refuses_stale_pool_base
|
|
434
|
+
test_stale_submodule_pin_explains_itself
|
|
435
|
+
test_unpushed_submodule_commit_is_still_uncommitted_work
|
|
436
|
+
test_work_inside_submodule_is_still_uncommitted_work
|
|
437
|
+
test_stale_pin_carrying_real_work_is_not_called_stale
|
|
438
|
+
test_stale_pin_beside_other_dirt_reports_one_verdict
|
|
439
|
+
|
|
440
|
+
echo "# all fm-spawn-pool-base-freshen tests passed"
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Regression test for the fm-spawn.sh treehouse-get worktree-detection settle
|
|
3
|
+
# loop (bin/fm-spawn.sh, the `for _ in $(seq 1 60)` loop after `treehouse get`).
|
|
4
|
+
#
|
|
5
|
+
# On some tmux/WSL setups a brand-new window's pane_current_path transiently
|
|
6
|
+
# reports a stale, unrelated-but-real path on the very first poll, before the
|
|
7
|
+
# pane actually settles into the worktree treehouse get moved it to. That stale
|
|
8
|
+
# path still passes the loop's "differs from the project" check and
|
|
9
|
+
# validate_spawn_worktree's "is a real, distinct worktree" check (it IS a real
|
|
10
|
+
# git checkout, just the wrong one), so a naive single-read loop silently
|
|
11
|
+
# records the wrong worktree= in state/<id>.meta. This test simulates that
|
|
12
|
+
# transient-then-settled pane_current_path sequence with a fake tmux and
|
|
13
|
+
# asserts the recorded worktree resolves to the real, settled worktree, never
|
|
14
|
+
# the stale first read.
|
|
15
|
+
set -u
|
|
16
|
+
|
|
17
|
+
# shellcheck source=tests/lib.sh
|
|
18
|
+
. "$(dirname "${BASH_SOURCE[0]}")/lib.sh"
|
|
19
|
+
|
|
20
|
+
SPAWN="$ROOT/bin/fm-spawn.sh"
|
|
21
|
+
TMP_ROOT=$(fm_test_tmproot fm-spawn-worktree-settle)
|
|
22
|
+
|
|
23
|
+
# make_settle_fakebin <dir> builds a fake tmux whose `#{pane_current_path}`
|
|
24
|
+
# query returns FM_FAKE_PANE_STALE for the first FM_FAKE_PANE_STALE_READS
|
|
25
|
+
# calls, then FM_FAKE_PANE_PATH forever after - reproducing a pane that
|
|
26
|
+
# transiently reports a stale cwd before settling into the real worktree.
|
|
27
|
+
make_settle_fakebin() {
|
|
28
|
+
local dir=$1 fakebin
|
|
29
|
+
fakebin=$(fm_fakebin "$dir")
|
|
30
|
+
cat > "$fakebin/tmux" <<'SH'
|
|
31
|
+
#!/usr/bin/env bash
|
|
32
|
+
set -u
|
|
33
|
+
case "$*" in
|
|
34
|
+
*"#{pane_current_path}"*)
|
|
35
|
+
countfile="${FM_FAKE_PANE_COUNTFILE:?FM_FAKE_PANE_COUNTFILE unset}"
|
|
36
|
+
n=0
|
|
37
|
+
[ -f "$countfile" ] && n=$(cat "$countfile")
|
|
38
|
+
n=$((n + 1))
|
|
39
|
+
printf '%s\n' "$n" > "$countfile"
|
|
40
|
+
if [ "$n" -le "${FM_FAKE_PANE_STALE_READS:-0}" ]; then
|
|
41
|
+
printf '%s\n' "${FM_FAKE_PANE_STALE:-}"
|
|
42
|
+
else
|
|
43
|
+
printf '%s\n' "${FM_FAKE_PANE_PATH:-}"
|
|
44
|
+
fi
|
|
45
|
+
exit 0
|
|
46
|
+
;;
|
|
47
|
+
esac
|
|
48
|
+
case "${1:-}" in
|
|
49
|
+
display-message) printf 'firstmate\n'; exit 0 ;;
|
|
50
|
+
list-windows) exit 0 ;;
|
|
51
|
+
has-session|new-session|new-window|kill-window) exit 0 ;;
|
|
52
|
+
send-keys) exit 0 ;;
|
|
53
|
+
esac
|
|
54
|
+
exit 0
|
|
55
|
+
SH
|
|
56
|
+
chmod +x "$fakebin/tmux"
|
|
57
|
+
fm_fake_exit0 "$fakebin" treehouse
|
|
58
|
+
printf '%s\n' "$fakebin"
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
# make_settle_case <name> <id> <stale_reads> builds a home, a primary project
|
|
62
|
+
# with a real worktree (the eventual settled path), and a separate real git
|
|
63
|
+
# repo standing in for the stale path (a real checkout of something else
|
|
64
|
+
# entirely, distinct from both the project and the worktree - mirroring the
|
|
65
|
+
# live incident where the stale read was another real firstmate home).
|
|
66
|
+
make_settle_case() {
|
|
67
|
+
local name=$1 id=$2 stale_reads=$3 case_dir home proj wt stale fakebin countfile
|
|
68
|
+
case_dir="$TMP_ROOT/$name"
|
|
69
|
+
home="$case_dir/home"
|
|
70
|
+
proj="$case_dir/project"
|
|
71
|
+
wt="$case_dir/wt"
|
|
72
|
+
stale="$case_dir/stale-other-checkout"
|
|
73
|
+
countfile="$case_dir/pane-call-count"
|
|
74
|
+
fakebin=$(make_settle_fakebin "$case_dir/fake")
|
|
75
|
+
mkdir -p "$home/data" "$home/projects" "$home/state" "$home/config"
|
|
76
|
+
printf 'codex\n' > "$home/config/crew-harness"
|
|
77
|
+
fm_git_worktree "$proj" "$wt" "wt-$name"
|
|
78
|
+
fm_git_init_commit "$stale"
|
|
79
|
+
mkdir -p "$home/data/$id"
|
|
80
|
+
printf 'brief for %s\n' "$id" > "$home/data/$id/brief.md"
|
|
81
|
+
touch "$home/state/.last-watcher-beat"
|
|
82
|
+
printf '%s\n' "$case_dir|$home|$proj|$wt|$stale|$fakebin|$countfile|$stale_reads"
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
read_settle_record() {
|
|
86
|
+
IFS='|' read -r _ HOME_DIR PROJ_DIR WT_DIR STALE_DIR FAKEBIN_DIR COUNTFILE STALE_READS <<EOF
|
|
87
|
+
$1
|
|
88
|
+
EOF
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
run_settle_spawn() {
|
|
92
|
+
local id=$1
|
|
93
|
+
FM_ROOT_OVERRIDE='' FM_HOME="$HOME_DIR" \
|
|
94
|
+
FM_STATE_OVERRIDE="$HOME_DIR/state" FM_DATA_OVERRIDE="$HOME_DIR/data" \
|
|
95
|
+
FM_PROJECTS_OVERRIDE="$HOME_DIR/projects" FM_CONFIG_OVERRIDE="$HOME_DIR/config" \
|
|
96
|
+
FM_SPAWN_NO_GUARD=1 TMUX="fake,1,0" \
|
|
97
|
+
FM_FAKE_PANE_PATH="$WT_DIR" FM_FAKE_PANE_STALE="$STALE_DIR" \
|
|
98
|
+
FM_FAKE_PANE_STALE_READS="$STALE_READS" FM_FAKE_PANE_COUNTFILE="$COUNTFILE" \
|
|
99
|
+
PATH="$FAKEBIN_DIR:$PATH" \
|
|
100
|
+
"$SPAWN" "$id" "$PROJ_DIR" --mode no-mistakes --yolo off 2>&1
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
# A single stale first read (the exact incident) must not be accepted: the
|
|
104
|
+
# loop should keep polling until two consecutive reads agree, landing on the
|
|
105
|
+
# real settled worktree instead.
|
|
106
|
+
test_single_stale_first_read_is_not_accepted() {
|
|
107
|
+
local rec id out status
|
|
108
|
+
id=settle-single-stale-z1
|
|
109
|
+
rec=$(make_settle_case settle-single "$id" 1)
|
|
110
|
+
read_settle_record "$rec"
|
|
111
|
+
|
|
112
|
+
out=$(run_settle_spawn "$id")
|
|
113
|
+
status=$?
|
|
114
|
+
expect_code 0 "$status" "spawn should succeed once the pane settles"
|
|
115
|
+
assert_contains "$out" "spawned $id" "spawn did not report success"
|
|
116
|
+
assert_grep "worktree=$WT_DIR" "$HOME_DIR/state/$id.meta" \
|
|
117
|
+
"meta did not record the settled worktree"
|
|
118
|
+
assert_no_grep "worktree=$STALE_DIR" "$HOME_DIR/state/$id.meta" \
|
|
119
|
+
"meta wrongly recorded the transient stale path as the worktree"
|
|
120
|
+
pass "a single transient stale pane_current_path read is not accepted as the worktree"
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
# A pane that reports the real worktree from the very first read still only
|
|
124
|
+
# costs the loop's existing one-second inter-poll sleep to confirm - not an
|
|
125
|
+
# extra full cycle on top of that.
|
|
126
|
+
test_already_settled_pane_costs_one_confirm_sleep() {
|
|
127
|
+
local rec id out status start end elapsed
|
|
128
|
+
id=settle-already-settled-z2
|
|
129
|
+
rec=$(make_settle_case settle-already-settled "$id" 0)
|
|
130
|
+
read_settle_record "$rec"
|
|
131
|
+
|
|
132
|
+
start=$(date +%s)
|
|
133
|
+
out=$(run_settle_spawn "$id")
|
|
134
|
+
status=$?
|
|
135
|
+
end=$(date +%s)
|
|
136
|
+
elapsed=$((end - start))
|
|
137
|
+
expect_code 0 "$status" "spawn should succeed when the pane is already settled"
|
|
138
|
+
assert_grep "worktree=$WT_DIR" "$HOME_DIR/state/$id.meta" \
|
|
139
|
+
"meta did not record the already-settled worktree"
|
|
140
|
+
[ "$elapsed" -le 5 ] || fail "already-settled pane took ${elapsed}s to confirm - expected close to the single inter-poll sleep"
|
|
141
|
+
pass "an already-settled pane confirms via the existing inter-poll sleep, not an extra full cycle"
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
test_single_stale_first_read_is_not_accepted
|
|
145
|
+
test_already_settled_pane_costs_one_confirm_sleep
|
|
146
|
+
|
|
147
|
+
echo "# all fm-spawn-worktree-settle tests passed"
|