@zerwiz/ymir 0.1.3 → 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 -39
- 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,107 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Acquire or inspect the per-home firstmate session lock.
|
|
3
|
+
# Writes the harness (agent) process PID found by walking the shell's ancestry,
|
|
4
|
+
# which lives as long as the firstmate session - unlike the transient subshell
|
|
5
|
+
# PID of any one tool call, which is dead moments after it is written.
|
|
6
|
+
# Usage: fm-lock.sh acquire; exit 1 unless ownership is verified
|
|
7
|
+
# fm-lock.sh status print holder and liveness; always exits 0
|
|
8
|
+
set -u
|
|
9
|
+
|
|
10
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
|
+
FM_ROOT="${FM_ROOT_OVERRIDE:-$(cd "$SCRIPT_DIR/.." && pwd)}"
|
|
12
|
+
FM_HOME="${FM_HOME:-${FM_ROOT_OVERRIDE:-$FM_ROOT}}"
|
|
13
|
+
STATE="${FM_STATE_OVERRIDE:-$FM_HOME/state}"
|
|
14
|
+
LOCK="$STATE/.lock"
|
|
15
|
+
mkdir -p "$STATE" 2>/dev/null || {
|
|
16
|
+
echo "error: cannot create session-lock state directory $STATE; operate read-only until resolved" >&2
|
|
17
|
+
exit 1
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
# Harness identity (FM_HARNESS_RE, ancestry walk, holder liveness) is owned by
|
|
21
|
+
# the shared session-lock lib so the Claude Stop auto-arm applies the exact
|
|
22
|
+
# same identity contract.
|
|
23
|
+
# shellcheck source=bin/fm-session-lock-lib.sh
|
|
24
|
+
. "$SCRIPT_DIR/fm-session-lock-lib.sh"
|
|
25
|
+
|
|
26
|
+
if [ "${1:-}" = "status" ]; then
|
|
27
|
+
if [ ! -f "$LOCK" ]; then echo "lock: free"; exit 0; fi
|
|
28
|
+
old=$(cat "$LOCK" 2>/dev/null) || {
|
|
29
|
+
echo "lock: unreadable"
|
|
30
|
+
exit 0
|
|
31
|
+
}
|
|
32
|
+
if fm_harness_pid_alive "$old"; then echo "lock: held by live harness pid $old"; else echo "lock: stale (pid $old dead or not a harness)"; fi
|
|
33
|
+
exit 0
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
me=$(fm_harness_ancestry_pid) || { echo "error: cannot locate harness process in ancestry" >&2; exit 1; }
|
|
37
|
+
probe=$(mktemp "$STATE/.lock-write.XXXXXX" 2>/dev/null) || {
|
|
38
|
+
echo "error: cannot write session lock; operate read-only until resolved" >&2
|
|
39
|
+
exit 1
|
|
40
|
+
}
|
|
41
|
+
rm -f "$probe" 2>/dev/null || {
|
|
42
|
+
echo "error: cannot clean session-lock publication probe; operate read-only until resolved" >&2
|
|
43
|
+
exit 1
|
|
44
|
+
}
|
|
45
|
+
# shellcheck source=bin/fm-wake-lib.sh
|
|
46
|
+
. "$SCRIPT_DIR/fm-wake-lib.sh"
|
|
47
|
+
CLAIM_LOCK="$STATE/.lock.acquire"
|
|
48
|
+
CLAIM_LOCK_HELD=0
|
|
49
|
+
release_claim_lock() {
|
|
50
|
+
if [ "$CLAIM_LOCK_HELD" -eq 1 ]; then
|
|
51
|
+
fm_lock_release "$CLAIM_LOCK"
|
|
52
|
+
CLAIM_LOCK_HELD=0
|
|
53
|
+
fi
|
|
54
|
+
}
|
|
55
|
+
trap release_claim_lock EXIT
|
|
56
|
+
trap 'exit 1' HUP INT TERM
|
|
57
|
+
|
|
58
|
+
if [ -f "$LOCK" ] && [ ! -L "$LOCK" ]; then
|
|
59
|
+
old=$(cat "$LOCK" 2>/dev/null || true)
|
|
60
|
+
if [ "$old" = "$me" ]; then
|
|
61
|
+
echo "lock acquired: harness pid $me"
|
|
62
|
+
exit 0
|
|
63
|
+
fi
|
|
64
|
+
if fm_harness_pid_alive "$old"; then
|
|
65
|
+
echo "error: another live firstmate session holds the lock (pid $old); operate read-only until resolved" >&2
|
|
66
|
+
exit 1
|
|
67
|
+
fi
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
if ! fm_lock_try_acquire "$CLAIM_LOCK"; then
|
|
71
|
+
sweep_pid=$(sed -n 's/^pid=//p' "$STATE/.startup-network.status" 2>/dev/null | tail -1)
|
|
72
|
+
if [ -n "${FM_LOCK_HELD_PID:-}" ] && [ "$FM_LOCK_HELD_PID" = "$sweep_pid" ]; then
|
|
73
|
+
echo "error: the prior session's bounded startup sweep is finishing; operate read-only until it releases the fleet lock" >&2
|
|
74
|
+
exit 1
|
|
75
|
+
fi
|
|
76
|
+
fm_lock_acquire_wait "$CLAIM_LOCK"
|
|
77
|
+
fi
|
|
78
|
+
CLAIM_LOCK_HELD=1
|
|
79
|
+
|
|
80
|
+
if [ -e "$LOCK" ] || [ -L "$LOCK" ]; then
|
|
81
|
+
if [ ! -f "$LOCK" ] || [ -L "$LOCK" ]; then
|
|
82
|
+
echo "error: session lock is not a regular file; operate read-only until resolved" >&2
|
|
83
|
+
exit 1
|
|
84
|
+
fi
|
|
85
|
+
old=$(cat "$LOCK" 2>/dev/null) || {
|
|
86
|
+
echo "error: session lock is unreadable; operate read-only until resolved" >&2
|
|
87
|
+
exit 1
|
|
88
|
+
}
|
|
89
|
+
if [ "$old" != "$me" ] && fm_harness_pid_alive "$old"; then
|
|
90
|
+
echo "error: another live firstmate session holds the lock (pid $old); operate read-only until resolved" >&2
|
|
91
|
+
exit 1
|
|
92
|
+
fi
|
|
93
|
+
fi
|
|
94
|
+
if ! { printf '%s\n' "$me" > "$LOCK"; } 2>/dev/null; then
|
|
95
|
+
echo "error: cannot write session lock; operate read-only until resolved" >&2
|
|
96
|
+
exit 1
|
|
97
|
+
fi
|
|
98
|
+
written=$(cat "$LOCK" 2>/dev/null) || {
|
|
99
|
+
echo "error: cannot verify session lock ownership; operate read-only until resolved" >&2
|
|
100
|
+
exit 1
|
|
101
|
+
}
|
|
102
|
+
if [ ! -f "$LOCK" ] || [ -L "$LOCK" ] || [ "$written" != "$me" ]; then
|
|
103
|
+
echo "error: session lock ownership verification failed; operate read-only until resolved" >&2
|
|
104
|
+
exit 1
|
|
105
|
+
fi
|
|
106
|
+
release_claim_lock
|
|
107
|
+
echo "lock acquired: harness pid $me"
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# fm-marker-lib.sh - compatibility entry point for from-firstmate routing.
|
|
3
|
+
#
|
|
4
|
+
# bin/fm-operational-input.sh owns current operational-input construction,
|
|
5
|
+
# parsing, marker bytes, and the established from-firstmate compatibility
|
|
6
|
+
# carrier. Existing callers source this path so they do not need a flag-day
|
|
7
|
+
# migration. No side effects on source. set -u / set -e safe.
|
|
8
|
+
|
|
9
|
+
_FM_MARKER_LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
10
|
+
# shellcheck source=bin/fm-operational-input.sh
|
|
11
|
+
. "$_FM_MARKER_LIB_DIR/fm-operational-input.sh"
|
|
12
|
+
unset _FM_MARKER_LIB_DIR
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Perform the approved local merge for a local-only ship task: fast-forward the
|
|
3
|
+
# project's default branch to the crewmate's fm/<id> branch.
|
|
4
|
+
#
|
|
5
|
+
# This is firstmate's merge gate-action (the captain's merge authority applied
|
|
6
|
+
# locally instead of via a GitHub PR). It is the one sanctioned exception to hard
|
|
7
|
+
# rule #1 "never run state-changing git in projects/", and it is narrow: it only
|
|
8
|
+
# runs for mode=local-only tasks, only after the captain approves (or yolo=on
|
|
9
|
+
# auto-approves), and only as a clean fast-forward - it refuses a diverged branch
|
|
10
|
+
# and tells you to have the crewmate rebase. See AGENTS.md prime directives,
|
|
11
|
+
# project management, and task lifecycle.
|
|
12
|
+
# Usage: fm-merge-local.sh <task-id>
|
|
13
|
+
set -eu
|
|
14
|
+
|
|
15
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
16
|
+
FM_ROOT="${FM_ROOT_OVERRIDE:-$(cd "$SCRIPT_DIR/.." && pwd)}"
|
|
17
|
+
FM_HOME="${FM_HOME:-${FM_ROOT_OVERRIDE:-$FM_ROOT}}"
|
|
18
|
+
STATE="${FM_STATE_OVERRIDE:-$FM_HOME/state}"
|
|
19
|
+
"$FM_ROOT/bin/fm-guard.sh" || true
|
|
20
|
+
# Role partition: landing local-only work is MAIN-owned; the Pi supervision
|
|
21
|
+
# branch reports readiness and never lands (contract: bin/fm-lease-lib.sh;
|
|
22
|
+
# no-op in homes without a branch actor).
|
|
23
|
+
# shellcheck source=bin/fm-lease-lib.sh
|
|
24
|
+
. "$SCRIPT_DIR/fm-lease-lib.sh"
|
|
25
|
+
fm_lease_forbid_branch "local-only landing (fm-merge-local)"
|
|
26
|
+
ID=${1:?usage: fm-merge-local.sh <task-id>}
|
|
27
|
+
META="$STATE/$ID.meta"
|
|
28
|
+
[ -f "$META" ] || { echo "error: no meta for task $ID at $META" >&2; exit 1; }
|
|
29
|
+
|
|
30
|
+
PROJ=$(grep '^project=' "$META" | cut -d= -f2-)
|
|
31
|
+
MODE=$(grep '^mode=' "$META" | cut -d= -f2- || true)
|
|
32
|
+
[ "$MODE" = local-only ] || { echo "error: task $ID is mode=$MODE, not local-only; merge PR tasks with bin/fm-pr-merge.sh <id> <PR url> after approval" >&2; exit 1; }
|
|
33
|
+
|
|
34
|
+
default_branch() {
|
|
35
|
+
local ref branch
|
|
36
|
+
ref=$(git -C "$PROJ" symbolic-ref --quiet --short refs/remotes/origin/HEAD 2>/dev/null || true)
|
|
37
|
+
if [ -n "$ref" ]; then
|
|
38
|
+
echo "${ref#origin/}"
|
|
39
|
+
return 0
|
|
40
|
+
fi
|
|
41
|
+
for branch in main master; do
|
|
42
|
+
if git -C "$PROJ" show-ref --verify --quiet "refs/heads/$branch"; then
|
|
43
|
+
echo "$branch"
|
|
44
|
+
return 0
|
|
45
|
+
fi
|
|
46
|
+
done
|
|
47
|
+
return 1
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
BRANCH="fm/$ID"
|
|
51
|
+
git -C "$PROJ" rev-parse --verify --quiet "refs/heads/$BRANCH" >/dev/null || { echo "error: branch $BRANCH does not exist in $PROJ" >&2; exit 1; }
|
|
52
|
+
|
|
53
|
+
DEFAULT=$(default_branch) || { echo "error: cannot determine default branch for $PROJ; expected origin/HEAD, main, or master" >&2; exit 1; }
|
|
54
|
+
|
|
55
|
+
# The project's main checkout must be on its default branch and clean, so the
|
|
56
|
+
# fast-forward lands predictably (firstmate never writes here otherwise).
|
|
57
|
+
cur=$(git -C "$PROJ" symbolic-ref --short HEAD 2>/dev/null || echo "")
|
|
58
|
+
[ "$cur" = "$DEFAULT" ] || { echo "error: $PROJ is on '$cur', expected default branch '$DEFAULT'; cannot merge safely" >&2; exit 1; }
|
|
59
|
+
if [ -n "$(git -C "$PROJ" status --porcelain 2>/dev/null | head -1)" ]; then
|
|
60
|
+
echo "error: $PROJ has a dirty working tree; refusing to merge into it" >&2
|
|
61
|
+
exit 1
|
|
62
|
+
fi
|
|
63
|
+
|
|
64
|
+
# Clean fast-forward only: DEFAULT must be an ancestor of BRANCH.
|
|
65
|
+
if ! git -C "$PROJ" merge-base --is-ancestor "$DEFAULT" "$BRANCH"; then
|
|
66
|
+
echo "REFUSED: $BRANCH is not a fast-forward of $DEFAULT (it has diverged)." >&2
|
|
67
|
+
echo "Have the crewmate rebase $BRANCH onto $DEFAULT, then retry." >&2
|
|
68
|
+
exit 1
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
before=$(git -C "$PROJ" rev-parse --short "$DEFAULT")
|
|
72
|
+
git -C "$PROJ" merge --ff-only "$BRANCH" >/dev/null
|
|
73
|
+
after=$(git -C "$PROJ" rev-parse --short "$DEFAULT")
|
|
74
|
+
echo "merged $BRANCH into local $DEFAULT ($before -> $after) in $PROJ"
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Shared durable, supervisor-facing outcome publication for a confirmed merge.
|
|
3
|
+
#
|
|
4
|
+
# Both a merge performed by this home and a merge detected by its existing poll
|
|
5
|
+
# use this operation, so neither outcome depends on an agent remembering it.
|
|
6
|
+
# This operation publishes the poll's local actionable row; the watcher
|
|
7
|
+
# immediately delivers that row as observation handling, not a second outcome
|
|
8
|
+
# path.
|
|
9
|
+
#
|
|
10
|
+
# The destination is the home's role, never the caller's choice:
|
|
11
|
+
# - a secondmate home reports upward to its parent on the same reply channel
|
|
12
|
+
# bin/fm-inactive-reconcile.sh's report_to_parent already uses, in the same
|
|
13
|
+
# "<state> [key=<slug>]: <note>" shape the charter contract defines;
|
|
14
|
+
# - a main home reports to the captain through the durable wake queue.
|
|
15
|
+
# A poll observed in a secondmate home also receives a local durable wake after
|
|
16
|
+
# the upward write, so the mate can handle its own poll observation.
|
|
17
|
+
# No new state file and no new transport are involved.
|
|
18
|
+
#
|
|
19
|
+
# Normal operation deduplicates the task's latest canonical PR identity through
|
|
20
|
+
# the merge-notification marker owned by bin/fm-pr-lib.sh. Main-home wake keys
|
|
21
|
+
# also include that PR identity so distinct PRs for a reused task remain
|
|
22
|
+
# distinct in queue presentation. The outcome is published before the marker
|
|
23
|
+
# is committed, so a failed commit stays eligible for at-least-once retry and
|
|
24
|
+
# may rarely duplicate rather than leave a merge silent.
|
|
25
|
+
#
|
|
26
|
+
# Sourced by bin/fm-pr-merge.sh, bin/fm-watch.sh, and tests. No side effects on
|
|
27
|
+
# source beyond its sourced libraries.
|
|
28
|
+
|
|
29
|
+
_FM_MERGE_OUTCOME_LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
30
|
+
# shellcheck source=bin/fm-pr-lib.sh
|
|
31
|
+
. "$_FM_MERGE_OUTCOME_LIB_DIR/fm-pr-lib.sh"
|
|
32
|
+
# shellcheck source=bin/fm-secondmate-parent-lib.sh
|
|
33
|
+
. "$_FM_MERGE_OUTCOME_LIB_DIR/fm-secondmate-parent-lib.sh"
|
|
34
|
+
|
|
35
|
+
# The secondmate identity of the home reporting, or non-zero when this home is
|
|
36
|
+
# a main home (1) or carries an unusable identity marker (2). Mirrors
|
|
37
|
+
# bin/fm-inactive-reconcile.sh's home_secondmate_id, which owns the same
|
|
38
|
+
# marker's contract.
|
|
39
|
+
fm_merge_outcome_home_id() { # <home>
|
|
40
|
+
local home=$1 marker id
|
|
41
|
+
marker="$home/.fm-secondmate-home"
|
|
42
|
+
if [ ! -e "$marker" ] && [ ! -L "$marker" ]; then
|
|
43
|
+
return 1
|
|
44
|
+
fi
|
|
45
|
+
[ -f "$marker" ] && [ ! -L "$marker" ] || return 2
|
|
46
|
+
[ "$(wc -c < "$marker")" -eq "$(LC_ALL=C tr -d '\0' < "$marker" | wc -c)" ] || return 2
|
|
47
|
+
id=$(cat "$marker" 2>/dev/null) || return 2
|
|
48
|
+
fm_pr_task_id_valid "$id" || return 2
|
|
49
|
+
printf '%s\n' "$id"
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
# Append <line> to <path> unless that exact line is already there, so a repeat
|
|
53
|
+
# report of the same merge cannot duplicate it.
|
|
54
|
+
fm_merge_outcome_append_once() { # <path> <line>
|
|
55
|
+
local path=$1 line=$2
|
|
56
|
+
[ ! -L "$path" ] || return 1
|
|
57
|
+
mkdir -p "$(dirname "$path")" || return 1
|
|
58
|
+
if grep -Fqx -- "$line" "$path" 2>/dev/null; then
|
|
59
|
+
return 0
|
|
60
|
+
fi
|
|
61
|
+
printf '%s\n' "$line" >> "$path"
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
# shellcheck disable=SC2034 # Public result consumed by sourcing callers.
|
|
65
|
+
FM_MERGE_OUTCOME_ALREADY_RECORDED=false
|
|
66
|
+
|
|
67
|
+
# fm_merge_outcome_report <home> <state> <task-id> <pr-url> <origin>
|
|
68
|
+
#
|
|
69
|
+
# <origin> says who observed the merge, because that decides whether the
|
|
70
|
+
# existing poll path also needs a local wake:
|
|
71
|
+
# self - this home performed the merge.
|
|
72
|
+
# poll - this home's merge poll detected the merge, so the canonical outcome
|
|
73
|
+
# also wakes this home after any upward hop needed by a secondmate.
|
|
74
|
+
#
|
|
75
|
+
# Returns 0 when the outcome is recorded (or already was), 2 on an invalid
|
|
76
|
+
# request, 3 when this home's own role or parent binding cannot be read well
|
|
77
|
+
# enough to say where the outcome belongs, and 1 on any other failure to
|
|
78
|
+
# record. A caller that has already merged must report a non-zero return rather
|
|
79
|
+
# than treat it as success: the merge landed and the record did not.
|
|
80
|
+
fm_merge_outcome_report() { # <home> <state> <task-id> <pr-url> <origin>
|
|
81
|
+
local home=$1 state=$2 id=$3 url=$4 origin=$5
|
|
82
|
+
local self='' self_rc=0 destination='' line lock status=0
|
|
83
|
+
local provider host path number
|
|
84
|
+
# shellcheck disable=SC2034 # Sourced wake helpers consume these scoped globals.
|
|
85
|
+
local STATE FM_WAKE_QUEUE FM_WAKE_QUEUE_LOCK
|
|
86
|
+
FM_MERGE_OUTCOME_ALREADY_RECORDED=false
|
|
87
|
+
case "$origin" in self|poll) ;; *) return 2 ;; esac
|
|
88
|
+
fm_pr_task_id_valid "$id" || return 2
|
|
89
|
+
fm_pr_url_parse "$url" || return 2
|
|
90
|
+
provider=$FM_PR_PROVIDER
|
|
91
|
+
host=$FM_PR_HOST
|
|
92
|
+
path=$FM_PR_PATH
|
|
93
|
+
number=$FM_PR_NUMBER
|
|
94
|
+
[ -d "$state" ] && [ ! -L "$state" ] || return 1
|
|
95
|
+
|
|
96
|
+
if self=$(fm_merge_outcome_home_id "$home"); then
|
|
97
|
+
fm_secondmate_parent_record_parse "$home/.fm-secondmate-parent" || return 3
|
|
98
|
+
case "$FM_SECONDMATE_PARENT_ROUTE" in
|
|
99
|
+
local)
|
|
100
|
+
[ -n "$FM_SECONDMATE_PARENT_HOME" ] || return 3
|
|
101
|
+
destination="$FM_SECONDMATE_PARENT_HOME/state/$self.status"
|
|
102
|
+
;;
|
|
103
|
+
remote) destination="$state/parent-replies.status" ;;
|
|
104
|
+
*) return 3 ;;
|
|
105
|
+
esac
|
|
106
|
+
line="done [key=merged-$id]: merged $id $FM_PR_URL"
|
|
107
|
+
else
|
|
108
|
+
self_rc=$?
|
|
109
|
+
[ "$self_rc" -eq 1 ] || return 3
|
|
110
|
+
fi
|
|
111
|
+
|
|
112
|
+
STATE=$state
|
|
113
|
+
# shellcheck source=bin/fm-wake-lib.sh
|
|
114
|
+
. "$_FM_MERGE_OUTCOME_LIB_DIR/fm-wake-lib.sh"
|
|
115
|
+
lock="$state/$id.pr-poll-merge-notified.lock"
|
|
116
|
+
fm_lock_acquire_wait "$lock" || return 1
|
|
117
|
+
if fm_pr_poll_merge_already_notified "$state" "$id" \
|
|
118
|
+
"$provider" "$host" "$path" "$number"; then
|
|
119
|
+
# shellcheck disable=SC2034 # Public result consumed by sourcing callers.
|
|
120
|
+
FM_MERGE_OUTCOME_ALREADY_RECORDED=true
|
|
121
|
+
fm_lock_release "$lock"
|
|
122
|
+
return 0
|
|
123
|
+
fi
|
|
124
|
+
|
|
125
|
+
if [ -n "$destination" ]; then
|
|
126
|
+
fm_merge_outcome_append_once "$destination" "$line" || status=1
|
|
127
|
+
fi
|
|
128
|
+
if [ "$status" -eq 0 ] && { [ "$origin" = poll ] || [ -z "$destination" ]; }; then
|
|
129
|
+
fm_wake_append check "merged-$id-$FM_PR_URL" \
|
|
130
|
+
"check: merge landed: $id $FM_PR_URL" || status=1
|
|
131
|
+
fi
|
|
132
|
+
if [ "$status" -eq 0 ]; then
|
|
133
|
+
fm_pr_poll_merge_mark_notified "$state" "$id" \
|
|
134
|
+
"$provider" "$host" "$path" "$number" || status=1
|
|
135
|
+
fi
|
|
136
|
+
fm_lock_release "$lock"
|
|
137
|
+
return "$status"
|
|
138
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Shared no-mistakes axi run attribution primitives.
|
|
3
|
+
#
|
|
4
|
+
# ONE owner for the no-mistakes run-attribution primitives used by
|
|
5
|
+
# fm-crew-state.sh (read-only current-state reporting) and fm-teardown.sh
|
|
6
|
+
# (pre-teardown run abort, see its "Fix 1" header comment). Teardown uses only
|
|
7
|
+
# strict branch-and-head identity; crew-state additionally permits the active
|
|
8
|
+
# pipeline-owned exemption defined below. Getting this wrong in either
|
|
9
|
+
# direction is unsafe: a false negative hides a genuinely parked run, and a
|
|
10
|
+
# false positive lets teardown act on a run it does not own.
|
|
11
|
+
#
|
|
12
|
+
# Bounded call to `no-mistakes "$@"` in dir $1, timeout $2 seconds. The bounded
|
|
13
|
+
# form preserves stdout, stderr, and exit status; the checked form discards
|
|
14
|
+
# stderr, while fm_nm_run keeps the fail-open query contract for read-only callers.
|
|
15
|
+
fm_nm_run_bounded() { # <dir> <timeout_secs> <args...>
|
|
16
|
+
local dir=$1 timeout_secs=$2 have_timeout=none
|
|
17
|
+
shift 2
|
|
18
|
+
if command -v timeout >/dev/null 2>&1; then have_timeout=timeout
|
|
19
|
+
elif command -v gtimeout >/dev/null 2>&1; then have_timeout=gtimeout
|
|
20
|
+
elif command -v perl >/dev/null 2>&1; then have_timeout=perl
|
|
21
|
+
fi
|
|
22
|
+
case "$have_timeout" in
|
|
23
|
+
timeout) ( cd "$dir" && timeout "$timeout_secs" no-mistakes "$@" ) ;;
|
|
24
|
+
gtimeout) ( cd "$dir" && gtimeout "$timeout_secs" no-mistakes "$@" ) ;;
|
|
25
|
+
perl) ( cd "$dir" && perl -e 'my $t = shift; my $pid = fork; die "fork failed" unless defined $pid; if (!$pid) { setpgrp(0, 0); exec @ARGV } local $SIG{ALRM} = sub { kill "TERM", -$pid; select undef, undef, undef, 0.2; kill "KILL", -$pid; exit 124 }; alarm $t; waitpid $pid, 0; exit($? >> 8)' "$timeout_secs" no-mistakes "$@" ) ;;
|
|
26
|
+
*) return 1 ;;
|
|
27
|
+
esac
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
fm_nm_run_checked() { # <dir> <timeout_secs> <args...>
|
|
31
|
+
fm_nm_run_bounded "$@" 2>/dev/null
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
fm_nm_run() { # <dir> <timeout_secs> <args...>
|
|
35
|
+
fm_nm_run_checked "$@" || true
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
fm_nm_trim() {
|
|
39
|
+
local s=${1:-}
|
|
40
|
+
s="${s#"${s%%[![:space:]]*}"}"
|
|
41
|
+
s="${s%"${s##*[![:space:]]}"}"
|
|
42
|
+
printf '%s' "$s"
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
fm_nm_strip_quotes() {
|
|
46
|
+
local s
|
|
47
|
+
s=$(fm_nm_trim "${1:-}")
|
|
48
|
+
case "$s" in
|
|
49
|
+
\"*\") s=${s#\"}; s=${s%\"} ;;
|
|
50
|
+
esac
|
|
51
|
+
fm_nm_trim "$s"
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
# Scalar value of a TOON key in captured `axi status` output $1.
|
|
55
|
+
fm_nm_field() { # <toon-output> <key>
|
|
56
|
+
printf '%s\n' "$1" | sed -n "s/^[[:space:]]*$2:[[:space:]]*\(.*\)/\1/p" | head -1
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
# 0 if run head $2 matches worktree $1's code identity, per the same rule
|
|
60
|
+
# everywhere this attribution is needed:
|
|
61
|
+
# - missing/empty head: cannot bind; reject
|
|
62
|
+
# - equal commits (short or full SHA): match
|
|
63
|
+
# - worktree HEAD is an ancestor of run head: match (pipeline fix commits on
|
|
64
|
+
# the same history advanced the run tip past local HEAD)
|
|
65
|
+
# - run head is a strict ancestor of worktree HEAD, or diverged: no match
|
|
66
|
+
# (local work advanced outside the run, or the branch tip was rewritten)
|
|
67
|
+
# fm_nm_run_is_pipeline_owned_active below carries the one exemption: a live
|
|
68
|
+
# run whose pipeline currently owns the branch binds without head equality.
|
|
69
|
+
fm_nm_head_matches_worktree() { # <worktree> <run_head>
|
|
70
|
+
local wt=$1 run_head=$2 local_full run_full
|
|
71
|
+
[ -n "$run_head" ] || return 1
|
|
72
|
+
local_full=$(git -C "$wt" rev-parse HEAD 2>/dev/null) || return 1
|
|
73
|
+
run_full=$(git -C "$wt" rev-parse --verify "${run_head}^{commit}" 2>/dev/null) || return 1
|
|
74
|
+
[ "$run_full" = "$local_full" ] && return 0
|
|
75
|
+
git -C "$wt" merge-base --is-ancestor "$local_full" "$run_full" 2>/dev/null
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
# 0 if head $2 resolves to a commit object in worktree $1 at all. This
|
|
79
|
+
# distinguishes a PROVEN mismatch (resolvable but not current: a historical or
|
|
80
|
+
# diverged head fm_nm_head_matches_worktree correctly rejects) from UNKNOWN
|
|
81
|
+
# attribution (unresolvable: e.g. a pipeline-owned lane head that never
|
|
82
|
+
# reached this worktree). A caller scanning run rows newest-first must stop on
|
|
83
|
+
# unknown attribution rather than surface an older, superseded run.
|
|
84
|
+
fm_nm_head_resolvable() { # <worktree> <head>
|
|
85
|
+
[ -n "$2" ] || return 1
|
|
86
|
+
git -C "$1" rev-parse --verify --quiet "$2^{commit}" >/dev/null 2>&1
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
# branch_sync.state from captured `axi status` TOON $1: the scalar directly
|
|
90
|
+
# under the top-level `branch_sync:` block. The first `state:` inside the
|
|
91
|
+
# block is the direct child (the nested local/pipeline/target/remote
|
|
92
|
+
# sub-blocks carry no `state:` key). Empty when the block is absent: no run
|
|
93
|
+
# on the current branch, another branch's run, or a CLI without branch sync.
|
|
94
|
+
fm_nm_branch_sync_state() { # <toon-output>
|
|
95
|
+
local s
|
|
96
|
+
s=$(printf '%s\n' "$1" \
|
|
97
|
+
| sed -n '/^[[:space:]]*branch_sync:[[:space:]]*$/,/^[^[:space:]][^:]*:/s/^[[:space:]]\{1,\}state:[[:space:]]*\(.*\)/\1/p' \
|
|
98
|
+
| head -1)
|
|
99
|
+
fm_nm_strip_quotes "$s"
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
# 0 if the run in captured `axi status` TOON $1 is still in flight: no
|
|
103
|
+
# terminal outcome and no terminal status.
|
|
104
|
+
fm_nm_run_is_active() { # <toon-output>
|
|
105
|
+
local status outcome
|
|
106
|
+
status=$(fm_nm_strip_quotes "$(fm_nm_field "$1" status)")
|
|
107
|
+
outcome=$(fm_nm_strip_quotes "$(fm_nm_field "$1" outcome)")
|
|
108
|
+
[ -z "$outcome" ] || return 1
|
|
109
|
+
case "$status" in completed|failed|cancelled) return 1 ;; esac
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
# The one exemption to the head rule above: while the pipeline OWNS the branch
|
|
113
|
+
# (branch_sync.state=pipeline_owned), the daemon's own branch attribution IS
|
|
114
|
+
# the attribution for an ACTIVE run, and
|
|
115
|
+
# head equality must not be required - the pipeline's lane head is routinely
|
|
116
|
+
# not a git object in the task worktree (rebase and fix commits that were
|
|
117
|
+
# never pushed back), so the head rule rejects exactly the run that is most
|
|
118
|
+
# current. The exemption never applies to a terminal run: a terminal run has
|
|
119
|
+
# released the branch, and binding one by branch name alone is the historical
|
|
120
|
+
# reused-branch misattribution the head rule exists to prevent.
|
|
121
|
+
fm_nm_run_is_pipeline_owned_active() { # <toon-output>
|
|
122
|
+
[ "$(fm_nm_branch_sync_state "$1")" = pipeline_owned ] || return 1
|
|
123
|
+
fm_nm_run_is_active "$1"
|
|
124
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Execute one tracked Firstmate command in a configured remote secondmate home.
|
|
3
|
+
#
|
|
4
|
+
# Usage:
|
|
5
|
+
# fm-on.sh [--stdin] <secondmate-id|unambiguous-ssh-alias> <fm-command> [args...]
|
|
6
|
+
#
|
|
7
|
+
# Routes come only from remote records in data/secondmates.md. A record names an
|
|
8
|
+
# SSH config alias, remote Firstmate code root, and remote FM_HOME. A host alias
|
|
9
|
+
# may be used directly only when exactly one record selects it; an ambiguous
|
|
10
|
+
# alias is refused. The command must be a genuine executable in this checkout's
|
|
11
|
+
# bin/fm-*.sh namespace. No per-command table exists.
|
|
12
|
+
#
|
|
13
|
+
# argv is encoded as one NUL-delimited stream and passed through the fixed
|
|
14
|
+
# fm-remote-entrypoint.sh. The remote command's stdin is /dev/null by default,
|
|
15
|
+
# because remote staging captures stdin to EOF and an open caller stream would
|
|
16
|
+
# block staging indefinitely; a payload caller passes --stdin to forward its
|
|
17
|
+
# own stream as the job's bounded input. stdout and stderr remain separate, and
|
|
18
|
+
# ssh's exit status is returned unchanged. OpenSSH never receives an auto-retry
|
|
19
|
+
# instruction here. Exit 255 therefore means unavailable transport or unknown
|
|
20
|
+
# remote completion and must be reconciled by the semantic caller, never
|
|
21
|
+
# blindly repeated by this layer.
|
|
22
|
+
#
|
|
23
|
+
# The SSH alias keeps normal public-key and strict host-key policy in ~/.ssh.
|
|
24
|
+
# This command explicitly disables agent forwarding, forwarding setup, and
|
|
25
|
+
# configured SendEnv patterns. The remote entrypoint executes the selected
|
|
26
|
+
# command under an empty environment with only its fixed runtime values.
|
|
27
|
+
#
|
|
28
|
+
# ServerAliveInterval/ServerAliveCountMax arm dead-peer detection so a vanished
|
|
29
|
+
# peer (a reboot, a dropped link) becomes a bounded ssh failure (exit 255)
|
|
30
|
+
# instead of an indefinite hang on a half-open TCP connection. The remote
|
|
31
|
+
# sshd answers keepalive probes independently of whatever the remote command
|
|
32
|
+
# is doing, so a legitimately long-but-alive remote command is never falsely
|
|
33
|
+
# killed. FM_SSH_ALIVE_INTERVAL and FM_SSH_ALIVE_COUNT_MAX override the
|
|
34
|
+
# defaults; the worst-case detection window is roughly interval * count.
|
|
35
|
+
set -eu
|
|
36
|
+
|
|
37
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
38
|
+
FM_ROOT="${FM_ROOT_OVERRIDE:-$(cd "$SCRIPT_DIR/.." && pwd)}"
|
|
39
|
+
FM_HOME="${FM_HOME:-${FM_ROOT_OVERRIDE:-$FM_ROOT}}"
|
|
40
|
+
DATA="${FM_DATA_OVERRIDE:-$FM_HOME/data}"
|
|
41
|
+
REG="$DATA/secondmates.md"
|
|
42
|
+
PROTOCOL=1
|
|
43
|
+
|
|
44
|
+
# shellcheck source=bin/fm-secondmate-registry-lib.sh
|
|
45
|
+
. "$SCRIPT_DIR/fm-secondmate-registry-lib.sh"
|
|
46
|
+
|
|
47
|
+
die() { printf 'error: %s\n' "$1" >&2; exit 1; }
|
|
48
|
+
usage() { sed -n '2,25p' "$0" | sed 's/^# \{0,1\}//'; exit 2; }
|
|
49
|
+
|
|
50
|
+
encode_base64() {
|
|
51
|
+
base64 | tr -d '\n'
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
STDIN_MODE=closed
|
|
55
|
+
if [ "${1:-}" = --stdin ]; then
|
|
56
|
+
STDIN_MODE=caller
|
|
57
|
+
shift
|
|
58
|
+
fi
|
|
59
|
+
[ "$#" -ge 2 ] || usage
|
|
60
|
+
ROUTE=$1
|
|
61
|
+
COMMAND=$2
|
|
62
|
+
shift 2
|
|
63
|
+
|
|
64
|
+
case "$ROUTE" in ''|-*|*[!A-Za-z0-9._-]*) die "remote route must be a safe secondmate id or SSH alias: $ROUTE" ;; esac
|
|
65
|
+
case "$COMMAND" in
|
|
66
|
+
fm-*.sh) ;;
|
|
67
|
+
*) die "remote command must be a basename in the fm-*.sh namespace: $COMMAND" ;;
|
|
68
|
+
esac
|
|
69
|
+
case "$COMMAND" in */*|*..*) die "remote command must not contain a path or traversal: $COMMAND" ;; esac
|
|
70
|
+
LOCAL_COMMAND="$FM_ROOT/bin/$COMMAND"
|
|
71
|
+
[ -f "$LOCAL_COMMAND" ] && [ ! -L "$LOCAL_COMMAND" ] && [ -x "$LOCAL_COMMAND" ] \
|
|
72
|
+
|| die "remote command is not a genuine tracked executable in this Firstmate checkout: $COMMAND"
|
|
73
|
+
git -C "$FM_ROOT" ls-files --error-unmatch "bin/$COMMAND" >/dev/null 2>&1 \
|
|
74
|
+
|| die "remote command is not tracked by this Firstmate checkout: $COMMAND"
|
|
75
|
+
[ -f "$REG" ] && [ ! -L "$REG" ] || die "no safe secondmate registry at $REG"
|
|
76
|
+
|
|
77
|
+
MATCHES=0
|
|
78
|
+
HOST=
|
|
79
|
+
ROOT=
|
|
80
|
+
HOME_PATH=
|
|
81
|
+
while IFS= read -r line || [ -n "$line" ]; do
|
|
82
|
+
case "$line" in '- '*) ;; *) continue ;; esac
|
|
83
|
+
secondmate_registry_parse_line "$line" || die "malformed secondmate registry entry: $line"
|
|
84
|
+
[ "$SECONDMATE_REGISTRY_REMOTE" -eq 1 ] || continue
|
|
85
|
+
if [ "$SECONDMATE_REGISTRY_ID" = "$ROUTE" ] || [ "$SECONDMATE_REGISTRY_HOST" = "$ROUTE" ]; then
|
|
86
|
+
MATCHES=$((MATCHES + 1))
|
|
87
|
+
HOST=$SECONDMATE_REGISTRY_HOST
|
|
88
|
+
ROOT=$SECONDMATE_REGISTRY_ROOT
|
|
89
|
+
HOME_PATH=$SECONDMATE_REGISTRY_HOME
|
|
90
|
+
fi
|
|
91
|
+
done < "$REG"
|
|
92
|
+
[ "$MATCHES" -gt 0 ] || die "no remote secondmate or SSH alias matches '$ROUTE'"
|
|
93
|
+
[ "$MATCHES" -eq 1 ] || die "remote route '$ROUTE' is ambiguous across $MATCHES configured secondmates; use a secondmate id"
|
|
94
|
+
case "$HOST" in ''|-*|*[!A-Za-z0-9._-]*) die "configured SSH alias is unsafe: $HOST" ;; esac
|
|
95
|
+
case "$ROOT" in /*) ;; *) die "configured remote root is not absolute: $ROOT" ;; esac
|
|
96
|
+
case "$HOME_PATH" in /*) ;; *) die "configured remote home is not absolute: $HOME_PATH" ;; esac
|
|
97
|
+
case "$ROOT$HOME_PATH" in *$'\n'*|*$'\r'*|*$'\t'*) die "configured remote root or home contains control characters" ;; esac
|
|
98
|
+
for configured_path in "$ROOT" "$HOME_PATH"; do
|
|
99
|
+
case "/$configured_path/" in */../*|*/./*) die "configured remote root or home contains traversal components" ;; esac
|
|
100
|
+
case "$configured_path" in *'//'*) die "configured remote root or home contains an empty path component" ;; esac
|
|
101
|
+
done
|
|
102
|
+
|
|
103
|
+
ROOT_B64=$(printf '%s' "$ROOT" | encode_base64)
|
|
104
|
+
HOME_B64=$(printf '%s' "$HOME_PATH" | encode_base64)
|
|
105
|
+
ARGV_B64=$(printf '%s\0' "$COMMAND" "$@" | encode_base64)
|
|
106
|
+
SSH_BIN=${FM_SSH_BIN:-ssh}
|
|
107
|
+
ALIVE_INTERVAL=${FM_SSH_ALIVE_INTERVAL:-15}
|
|
108
|
+
ALIVE_COUNT_MAX=${FM_SSH_ALIVE_COUNT_MAX:-3}
|
|
109
|
+
case "$ALIVE_INTERVAL" in ''|*[!0-9]*) die "FM_SSH_ALIVE_INTERVAL must be a positive integer: $ALIVE_INTERVAL" ;; esac
|
|
110
|
+
case "$ALIVE_COUNT_MAX" in ''|*[!0-9]*) die "FM_SSH_ALIVE_COUNT_MAX must be a positive integer: $ALIVE_COUNT_MAX" ;; esac
|
|
111
|
+
[ "$ALIVE_INTERVAL" -gt 0 ] || die "FM_SSH_ALIVE_INTERVAL must be a positive integer: $ALIVE_INTERVAL"
|
|
112
|
+
[ "$ALIVE_COUNT_MAX" -gt 0 ] || die "FM_SSH_ALIVE_COUNT_MAX must be a positive integer: $ALIVE_COUNT_MAX"
|
|
113
|
+
|
|
114
|
+
SSH_ARGS=(
|
|
115
|
+
-o ForwardAgent=no
|
|
116
|
+
-o ClearAllForwardings=yes
|
|
117
|
+
-o 'SendEnv=-*'
|
|
118
|
+
-o "ServerAliveInterval=$ALIVE_INTERVAL"
|
|
119
|
+
-o "ServerAliveCountMax=$ALIVE_COUNT_MAX"
|
|
120
|
+
-- "$HOST" fm-remote-entrypoint.sh "$PROTOCOL" "$ROOT_B64" "$HOME_B64" "$ARGV_B64"
|
|
121
|
+
)
|
|
122
|
+
if [ "$STDIN_MODE" = caller ]; then
|
|
123
|
+
exec "$SSH_BIN" "${SSH_ARGS[@]}"
|
|
124
|
+
fi
|
|
125
|
+
exec "$SSH_BIN" "${SSH_ARGS[@]}" < /dev/null
|