@zerwiz/ymir 0.1.4 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/README.md +291 -0
- package/.agents/agents/bragi-marketer.md +111 -0
- package/.agents/agents/brokk.md +352 -0
- package/.agents/agents/forseti-reviewer.md +93 -0
- package/.agents/agents/frigg-consent.md +77 -0
- package/.agents/agents/groa-update.md +77 -0
- package/.agents/agents/hnoss-designer.md +69 -0
- package/.agents/agents/huginn-researcher.md +99 -0
- package/.agents/agents/jord-projects.md +78 -0
- package/.agents/agents/kvasir-scout.md +91 -0
- package/.agents/agents/mimir-planner.md +92 -0
- package/.agents/agents/muninn-stow.md +77 -0
- package/.agents/agents/saga-bearings.md +78 -0
- package/.agents/agents/sindri-developer.md +114 -0
- package/.agents/agents/snotra-documenter.md +105 -0
- package/.agents/agents/syn-recovery.md +78 -0
- package/.agents/agents/tyr-check.md +78 -0
- package/.agents/agents/urdh-hold.md +77 -0
- package/.agents/agents/volundr-smith.md +80 -0
- package/.agents/agents/vor-diagnostics.md +77 -0
- package/.agents/assets/agents/naming.md +50 -0
- package/.agents/assets/agents/registry.md +93 -0
- package/.agents/assets/agents/runtime.md +36 -0
- package/.agents/assets/agents/toon-tasks-cli.md +42 -0
- package/.agents/assets/templates/company_entity.template.md +37 -0
- package/.agents/backend/backends/cmux.sh +649 -0
- package/.agents/backend/backends/herdr-eventwait.py +157 -0
- package/.agents/backend/backends/herdr-workspace-move.py +114 -0
- package/.agents/backend/backends/herdr.sh +3386 -0
- package/.agents/backend/backends/orca.sh +290 -0
- package/.agents/backend/backends/tmux.sh +357 -0
- package/.agents/backend/backends/zellij.sh +700 -0
- package/.agents/backend/fm-afk-launch.sh +654 -0
- package/.agents/backend/fm-afk-return.sh +241 -0
- package/.agents/backend/fm-afk-start.sh +172 -0
- package/.agents/backend/fm-arm-command-policy.mjs +960 -0
- package/.agents/backend/fm-arm-pretool-check.sh +200 -0
- package/.agents/backend/fm-backend-hometag-lib.sh +52 -0
- package/.agents/backend/fm-backend.sh +981 -0
- package/.agents/backend/fm-backlog-handoff.sh +909 -0
- package/.agents/backend/fm-backlog-receive.sh +187 -0
- package/.agents/backend/fm-backlog-transition-lib.sh +779 -0
- package/.agents/backend/fm-bearings-board.sh +204 -0
- package/.agents/backend/fm-bearings-snapshot.sh +546 -0
- package/.agents/backend/fm-bootstrap.sh +1568 -0
- package/.agents/backend/fm-branch-outcome.sh +203 -0
- package/.agents/backend/fm-branch-prompt.sh +101 -0
- package/.agents/backend/fm-brief.sh +452 -0
- package/.agents/backend/fm-busy-event.sh +234 -0
- package/.agents/backend/fm-busy-lib.sh +986 -0
- package/.agents/backend/fm-captain-hold.sh +1001 -0
- package/.agents/backend/fm-cd-command-policy.mjs +153 -0
- package/.agents/backend/fm-cd-pretool-check.sh +190 -0
- package/.agents/backend/fm-check-lib.sh +74 -0
- package/.agents/backend/fm-check-register.sh +42 -0
- package/.agents/backend/fm-check-unregister.sh +52 -0
- package/.agents/backend/fm-classify-lib.sh +1770 -0
- package/.agents/backend/fm-claude-stop-autoarm.sh +334 -0
- package/.agents/backend/fm-composer-lib.sh +1416 -0
- package/.agents/backend/fm-config-inherit-lib.sh +1202 -0
- package/.agents/backend/fm-config-push.sh +254 -0
- package/.agents/backend/fm-control-lib.sh +251 -0
- package/.agents/backend/fm-control.sh +878 -0
- package/.agents/backend/fm-crew-state.sh +625 -0
- package/.agents/backend/fm-cursor-lib.sh +243 -0
- package/.agents/backend/fm-decision-hold.sh +232 -0
- package/.agents/backend/fm-doc-audience-check.sh +269 -0
- package/.agents/backend/fm-dod-lib.sh +67 -0
- package/.agents/backend/fm-ensure-agents-md.sh +253 -0
- package/.agents/backend/fm-extension-launch-barrier.mjs +129 -0
- package/.agents/backend/fm-extension.mjs +2577 -0
- package/.agents/backend/fm-extension.sh +16 -0
- package/.agents/backend/fm-ff-lib.sh +420 -0
- package/.agents/backend/fm-fleet-snapshot.sh +1463 -0
- package/.agents/backend/fm-fleet-sync.sh +458 -0
- package/.agents/backend/fm-fleet-view.sh +96 -0
- package/.agents/backend/fm-gate-refuse-lib.sh +102 -0
- package/.agents/backend/fm-guard.sh +242 -0
- package/.agents/backend/fm-harness.sh +195 -0
- package/.agents/backend/fm-herdr-ci-cleanup.sh +115 -0
- package/.agents/backend/fm-herdr-lab.sh +346 -0
- package/.agents/backend/fm-herdr-session-cleanup.sh +337 -0
- package/.agents/backend/fm-home-seed.sh +984 -0
- package/.agents/backend/fm-home-summary-refresh.sh +255 -0
- package/.agents/backend/fm-hook-host-lib.sh +36 -0
- package/.agents/backend/fm-inactive-reconcile.sh +531 -0
- package/.agents/backend/fm-inbox.sh +399 -0
- package/.agents/backend/fm-install-actionlint.sh +84 -0
- package/.agents/backend/fm-install-herdr.sh +96 -0
- package/.agents/backend/fm-install-shellcheck.sh +84 -0
- package/.agents/backend/fm-install-treehouse.sh +95 -0
- package/.agents/backend/fm-kimi-turnend-hook.sh +276 -0
- package/.agents/backend/fm-lease-lib.sh +218 -0
- package/.agents/backend/fm-lease.sh +189 -0
- package/.agents/backend/fm-line-cap-lib.sh +51 -0
- package/.agents/backend/fm-lint-workflows.sh +137 -0
- package/.agents/backend/fm-lint.sh +591 -0
- package/.agents/backend/fm-lock-lib.sh +104 -0
- package/.agents/backend/fm-lock.sh +107 -0
- package/.agents/backend/fm-marker-lib.sh +12 -0
- package/.agents/backend/fm-merge-local.sh +74 -0
- package/.agents/backend/fm-merge-outcome-lib.sh +138 -0
- package/.agents/backend/fm-nm-run-lib.sh +124 -0
- package/.agents/backend/fm-on.sh +125 -0
- package/.agents/backend/fm-operational-input.sh +253 -0
- package/.agents/backend/fm-peek.sh +46 -0
- package/.agents/backend/fm-pending-reply-lib.sh +1409 -0
- package/.agents/backend/fm-pr-check.sh +135 -0
- package/.agents/backend/fm-pr-lib.sh +1016 -0
- package/.agents/backend/fm-pr-merge.sh +707 -0
- package/.agents/backend/fm-pr-poll.sh +110 -0
- package/.agents/backend/fm-primary-scope-lib.sh +33 -0
- package/.agents/backend/fm-procevent-extension-capture.pl +259 -0
- package/.agents/backend/fm-procevent-lavish.sh +628 -0
- package/.agents/backend/fm-procevent-lib.sh +892 -0
- package/.agents/backend/fm-procevent-quota.sh +290 -0
- package/.agents/backend/fm-procevent-remote-reply.sh +577 -0
- package/.agents/backend/fm-procevent-when.sh +504 -0
- package/.agents/backend/fm-procevent.sh +1466 -0
- package/.agents/backend/fm-project-mode.sh +92 -0
- package/.agents/backend/fm-project-origin-lib.sh +180 -0
- package/.agents/backend/fm-promote.sh +282 -0
- package/.agents/backend/fm-public-followup-emit.sh +260 -0
- package/.agents/backend/fm-public-followup-lib.sh +398 -0
- package/.agents/backend/fm-public-followup.sh +1330 -0
- package/.agents/backend/fm-push-transition-lib.sh +168 -0
- package/.agents/backend/fm-quota-axi-lib.sh +93 -0
- package/.agents/backend/fm-quota-choose.sh +384 -0
- package/.agents/backend/fm-remote-delta-read.sh +189 -0
- package/.agents/backend/fm-remote-doctor.sh +800 -0
- package/.agents/backend/fm-remote-entrypoint.sh +193 -0
- package/.agents/backend/fm-remote-file.sh +234 -0
- package/.agents/backend/fm-remote-home-provision.sh +259 -0
- package/.agents/backend/fm-remote-home-seed.sh +259 -0
- package/.agents/backend/fm-remote-inherit-push.sh +90 -0
- package/.agents/backend/fm-remote-inherit.sh +179 -0
- package/.agents/backend/fm-remote-job-lib.sh +1241 -0
- package/.agents/backend/fm-remote-job-reap-orphans.sh +137 -0
- package/.agents/backend/fm-remote-job-worker.sh +1124 -0
- package/.agents/backend/fm-remote-readiness-lib.sh +44 -0
- package/.agents/backend/fm-remote-secondmate-control.sh +340 -0
- package/.agents/backend/fm-review-diff.sh +158 -0
- package/.agents/backend/fm-secondmate-charter-lib.sh +44 -0
- package/.agents/backend/fm-secondmate-nudge-lib.sh +68 -0
- package/.agents/backend/fm-secondmate-parent-lib.sh +70 -0
- package/.agents/backend/fm-secondmate-reconcile.sh +371 -0
- package/.agents/backend/fm-secondmate-registry-lib.sh +311 -0
- package/.agents/backend/fm-secondmate-report.sh +88 -0
- package/.agents/backend/fm-send.sh +1059 -0
- package/.agents/backend/fm-session-lock-lib.sh +176 -0
- package/.agents/backend/fm-session-start.sh +970 -0
- package/.agents/backend/fm-sessionstart-cursor.sh +40 -0
- package/.agents/backend/fm-sessionstart-nudge.sh +45 -0
- package/.agents/backend/fm-sessionstart-run.sh +145 -0
- package/.agents/backend/fm-spawn.sh +3153 -0
- package/.agents/backend/fm-startup-memory-budget-lib.sh +224 -0
- package/.agents/backend/fm-startup-memory-budget.sh +94 -0
- package/.agents/backend/fm-startup-network.sh +642 -0
- package/.agents/backend/fm-stow-cascade.sh +251 -0
- package/.agents/backend/fm-subagent-pretool-check.sh +207 -0
- package/.agents/backend/fm-supervise-daemon.sh +1732 -0
- package/.agents/backend/fm-supervision-instructions.sh +215 -0
- package/.agents/backend/fm-supervision-lib.sh +90 -0
- package/.agents/backend/fm-supervisor-target-lib.sh +78 -0
- package/.agents/backend/fm-tangle-lib.sh +53 -0
- package/.agents/backend/fm-task-inbox-lib.sh +402 -0
- package/.agents/backend/fm-tasks-axi-lib.sh +123 -0
- package/.agents/backend/fm-teardown.sh +2922 -0
- package/.agents/backend/fm-test-isolation-proof.sh +588 -0
- package/.agents/backend/fm-test-run.sh +2191 -0
- package/.agents/backend/fm-timeout-lib.sh +141 -0
- package/.agents/backend/fm-timing-lib.sh +179 -0
- package/.agents/backend/fm-tmux-lib.sh +291 -0
- package/.agents/backend/fm-tool-update-check.sh +898 -0
- package/.agents/backend/fm-trace-context-lib.sh +227 -0
- package/.agents/backend/fm-transition-lib.sh +103 -0
- package/.agents/backend/fm-turnend-guard-cursor.sh +391 -0
- package/.agents/backend/fm-turnend-guard-grok.sh +90 -0
- package/.agents/backend/fm-turnend-guard.sh +432 -0
- package/.agents/backend/fm-update.sh +110 -0
- package/.agents/backend/fm-vendor-auth-probe.sh +190 -0
- package/.agents/backend/fm-voice-client.py +1373 -0
- package/.agents/backend/fm-voice-relay.py +1256 -0
- package/.agents/backend/fm-wake-drain.sh +592 -0
- package/.agents/backend/fm-wake-grant.sh +127 -0
- package/.agents/backend/fm-wake-lib.sh +1849 -0
- package/.agents/backend/fm-watch-arm.sh +602 -0
- package/.agents/backend/fm-watch-checkpoint.sh +109 -0
- package/.agents/backend/fm-watch.sh +1962 -0
- package/.agents/backend/fm-x-dismiss.sh +116 -0
- package/.agents/backend/fm-x-followup.sh +286 -0
- package/.agents/backend/fm-x-lib.sh +1000 -0
- package/.agents/backend/fm-x-link.sh +234 -0
- package/.agents/backend/fm-x-poll.sh +185 -0
- package/.agents/backend/fm-x-reply.sh +385 -0
- package/.agents/backend/fm_voice_frame.py +166 -0
- package/.agents/backend/fm_voice_records.py +574 -0
- package/.agents/backend/model-bridge.py +290 -0
- package/.agents/backend/opencode-go-bridge.py +30 -0
- package/.agents/bus/README.md +12 -0
- package/.agents/bus/messages.json +1 -0
- package/.agents/config/agents.machine.example.yaml +16 -0
- package/.agents/config/agents.yaml +50 -0
- package/.agents/config/agents.yaml.example +72 -0
- package/.agents/config/crew-dispatch.json +22 -0
- package/.agents/config/cron.yaml +9 -0
- package/.agents/config/eindri-dispatch.json +67 -0
- package/.agents/config/eindri-harness +1 -0
- package/.agents/config/startup-memory-budget +1 -0
- package/.agents/config/tailscale-sync.yaml +27 -0
- package/.agents/filebrowser/.filebrowser.json +6 -0
- package/.agents/filebrowser/README.md +11 -0
- package/.agents/gateway/README.md +12 -0
- package/.agents/github/README.md +15 -0
- package/.agents/github/webhooks/.gitkeep +0 -0
- package/.agents/github/workflows/.gitkeep +0 -0
- package/.agents/harness/opencode/plugins/lib/rodd-operational-input.js +37 -0
- package/.agents/harness/opencode/plugins/package.json +4 -0
- package/.agents/harness/opencode/plugins/saga-sessionstart.js +77 -0
- package/.agents/harness/opencode/plugins/syn-cd-check.js +61 -0
- package/.agents/harness/opencode/plugins/syn-pretool-check.js +68 -0
- package/.agents/harness/opencode/plugins/syn-turnend-guard.js +105 -0
- package/.agents/harness/opencode/plugins/syn-watch-arm.js +521 -0
- package/.agents/memory/README.md +46 -0
- package/.agents/memory/kaia.engram +0 -0
- package/.agents/memory/kaia.engram-shm +0 -0
- package/.agents/memory/kaia.engram-wal +0 -0
- package/.agents/memory/runes_audit.md +5 -0
- package/.agents/memory/well/episodes.jsonl +367 -0
- package/.agents/memory/well/workspace.jsonl +27 -0
- package/.agents/migrations/0001-hodd-layout.sh +38 -0
- package/.agents/migrations/0002-a2a-mcp.sh +27 -0
- package/.agents/migrations/0003-private-data-separation.sh +111 -0
- package/.agents/migrations/0004-hoard-and-realms.sh +104 -0
- package/.agents/sandbox/Dockerfile.utgard +19 -0
- package/.agents/sandbox/README.md +14 -0
- package/.agents/sandbox/utgard.config.json +14 -0
- package/.agents/skills/README.md +59 -0
- package/.agents/skills/bragi-marketing/README.md +3 -0
- package/.agents/skills/bragi-marketing/SKILL.md +82 -0
- package/.agents/skills/eindri-homes/README.md +3 -0
- package/.agents/skills/eindri-homes/SKILL.md +291 -0
- package/.agents/skills/eindri-homes/assets/control-plane.md +122 -0
- package/.agents/skills/eindri-homes/assets/dispatch.md +80 -0
- package/.agents/skills/frigg-consent/README.md +3 -0
- package/.agents/skills/frigg-consent/SKILL.md +56 -0
- package/.agents/skills/galdr-ymirsystem/README.md +3 -0
- package/.agents/skills/galdr-ymirsystem/SKILL.md +158 -0
- package/.agents/skills/galdr-ymirsystem/assets/README.md +74 -0
- package/.agents/skills/galdr-ymirsystem/assets/brokk-distro-runtime.md +390 -0
- package/.agents/skills/galdr-ymirsystem/assets/build-method.md +113 -0
- package/.agents/skills/galdr-ymirsystem/assets/build-tool-categories.md +178 -0
- package/.agents/skills/galdr-ymirsystem/assets/eindri-orchestration.md +518 -0
- package/.agents/skills/galdr-ymirsystem/assets/eindri-profiles.md +136 -0
- package/.agents/skills/galdr-ymirsystem/assets/harness-integration/README.md +673 -0
- package/.agents/skills/galdr-ymirsystem/assets/harness-integration/claude-code.md +197 -0
- package/.agents/skills/galdr-ymirsystem/assets/harness-integration/codex.md +191 -0
- package/.agents/skills/galdr-ymirsystem/assets/harness-integration/cursor.md +193 -0
- package/.agents/skills/galdr-ymirsystem/assets/harness-integration/opencode.md +262 -0
- package/.agents/skills/galdr-ymirsystem/assets/harness-integration/pi.md +295 -0
- package/.agents/skills/galdr-ymirsystem/assets/hlidskjalf-ui.md +496 -0
- package/.agents/skills/galdr-ymirsystem/assets/installation.md +571 -0
- package/.agents/skills/galdr-ymirsystem/assets/local-models/HOST-DATA.example.md +72 -0
- package/.agents/skills/galdr-ymirsystem/assets/local-models.md +274 -0
- package/.agents/skills/galdr-ymirsystem/assets/memory-well.md +161 -0
- package/.agents/skills/galdr-ymirsystem/assets/nornir-jobs.md +377 -0
- package/.agents/skills/galdr-ymirsystem/assets/norse-naming.md +325 -0
- package/.agents/skills/galdr-ymirsystem/assets/odrerir-hall.md +129 -0
- package/.agents/skills/galdr-ymirsystem/assets/pi-boot/einherjar-spawn.schema.json +81 -0
- package/.agents/skills/galdr-ymirsystem/assets/pi-boot/herdr-profile.toml +75 -0
- package/.agents/skills/galdr-ymirsystem/assets/pi-boot/pi-profile.yml +96 -0
- package/.agents/skills/galdr-ymirsystem/assets/pi-boot/supervision-tree.yml +163 -0
- package/.agents/skills/galdr-ymirsystem/assets/pi-boot-guide.md +58 -0
- package/.agents/skills/galdr-ymirsystem/assets/porting-upstream-to-norse.md +301 -0
- package/.agents/skills/galdr-ymirsystem/assets/principles.md +385 -0
- package/.agents/skills/galdr-ymirsystem/assets/reference-adoption.md +99 -0
- package/.agents/skills/galdr-ymirsystem/assets/registry.md +379 -0
- package/.agents/skills/galdr-ymirsystem/assets/runtime-compliance.md +463 -0
- package/.agents/skills/galdr-ymirsystem/assets/runtime-components.md +553 -0
- package/.agents/skills/galdr-ymirsystem/assets/smidja.md +175 -0
- package/.agents/skills/galdr-ymirsystem/schemas/toon-schemas.md +190 -0
- package/.agents/skills/galdr-ymirsystem/scripts/README.md +45 -0
- package/.agents/skills/galdr-ymirsystem/scripts/bench-one.sh +248 -0
- package/.agents/skills/galdr-ymirsystem/scripts/compliance-check.sh +360 -0
- package/.agents/skills/galdr-ymirsystem/scripts/gpu-sample.sh +43 -0
- package/.agents/skills/galdr-ymirsystem/scripts/stop-all.sh +34 -0
- package/.agents/skills/galdr-ymirsystem/scripts/toon-check.py +188 -0
- package/.agents/skills/gjallarhorn-relay/README.md +3 -0
- package/.agents/skills/gjallarhorn-relay/SKILL.md +283 -0
- package/.agents/skills/groa-update/SKILL.md +70 -0
- package/.agents/skills/hamr-adapters/README.md +3 -0
- package/.agents/skills/hamr-adapters/SKILL.md +123 -0
- package/.agents/skills/hamr-adapters/references/common/control-and-recovery.md +37 -0
- package/.agents/skills/hamr-adapters/references/common/dispatch.md +32 -0
- package/.agents/skills/hamr-adapters/references/common/model-and-effort.md +42 -0
- package/.agents/skills/hamr-adapters/references/common/primary-hooks.md +40 -0
- package/.agents/skills/hamr-adapters/references/harness/claude.md +55 -0
- package/.agents/skills/hamr-adapters/references/harness/codex.md +43 -0
- package/.agents/skills/hamr-adapters/references/harness/cursor.md +75 -0
- package/.agents/skills/hamr-adapters/references/harness/grok.md +69 -0
- package/.agents/skills/hamr-adapters/references/harness/kimi.md +51 -0
- package/.agents/skills/hamr-adapters/references/harness/muse.md +70 -0
- package/.agents/skills/hamr-adapters/references/harness/opencode.md +42 -0
- package/.agents/skills/hamr-adapters/references/harness/pi.md +56 -0
- package/.agents/skills/herdr-panes/README.md +3 -0
- package/.agents/skills/herdr-panes/SKILL.md +92 -0
- package/.agents/skills/herdr-panes/assets/herdr-backend.md +346 -0
- package/.agents/skills/herdr-panes/assets/tmux-backend.md +115 -0
- package/.agents/skills/hnoss-design/DESIGN.md +19 -0
- package/.agents/skills/hnoss-design/README.md +3 -0
- package/.agents/skills/hnoss-design/SKILL.md +83 -0
- package/.agents/skills/hvild-afk/README.md +3 -0
- package/.agents/skills/hvild-afk/SKILL.md +241 -0
- package/.agents/skills/jord-projects/README.md +3 -0
- package/.agents/skills/jord-projects/SKILL.md +92 -0
- package/.agents/skills/lifecycle/SKILL.md +56 -0
- package/.agents/skills/lifecycle/smoke_test.sh +52 -0
- package/.agents/skills/lifecycle/start.sh +21 -0
- package/.agents/skills/lifecycle/status.sh +35 -0
- package/.agents/skills/lifecycle/stop.sh +16 -0
- package/.agents/skills/muninn-stow/README.md +3 -0
- package/.agents/skills/muninn-stow/SKILL.md +309 -0
- package/.agents/skills/no-mistakes/SKILL.md +379 -0
- package/.agents/skills/nornir-schedule/README.md +3 -0
- package/.agents/skills/nornir-schedule/SKILL.md +25 -0
- package/.agents/skills/nornir-schedule/assets/events.md +137 -0
- package/.agents/skills/nornir-schedule/assets/quota.md +131 -0
- package/.agents/skills/nsr-compliance/README.md +3 -0
- package/.agents/skills/nsr-compliance/SKILL.md +29 -0
- package/.agents/skills/nsr-compliance/assets/nsr/README.md +40 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/RULES/README.md +15 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/RULES/git-workflow.md +18 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/RULES/security.md +22 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/RULES/tech-stack.md +8 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/SKILL.md +71 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/config/core_four.yaml +16 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/gates/check_danger.sh +102 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/gates/check_wiring.sh +69 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/gates/validate_code.sh +29 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/gates/verify_docs.py +66 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/generate.sh +109 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/harness/envelopes/result_envelope.json +14 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/harness/envelopes/task_envelope.json +20 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/harness/runner.py +303 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/telemetry/logger.py +112 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/README.md +18 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/config/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/gates/README.md +12 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/gates/check_env.sh +23 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/gates/check_paths.sh +20 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/gates/check_platform.sh +23 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/harness/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/harness/envelopes/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/installer/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/installer/install.sh +125 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/telemetry/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/README.md +20 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/features/README.md +36 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/features/SKILL-template.md +14 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/README.md +25 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/SKILL.md +13 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/create_branch.sh +6 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/safe_commit.sh +9 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/sync_upstream.sh +6 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/README.md +27 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/SKILL.md +15 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/smoke_test.sh +12 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/start.sh +19 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/status.sh +12 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/stop.sh +15 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/README.md +18 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/config/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/config/core_four.yaml +13 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/README.md +12 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_danger.sh +102 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_env.sh +23 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_paths.sh +20 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_platform.sh +23 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_wiring.sh +69 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/envelopes/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/envelopes/result_envelope.json +14 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/envelopes/task_envelope.json +20 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/runner.py +303 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/installer/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/installer/install.sh +125 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/telemetry/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/telemetry/logger.py +112 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/BEST_PRACTICES/README.md +14 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/BEST_PRACTICES/api.md +17 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/BEST_PRACTICES/compliance-wiring.md +155 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/BEST_PRACTICES/frontend.md +15 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/README.md +23 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/clients/README.md +16 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/clients/template-README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/deploy.sh +49 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/envs/README.md +12 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/envs/development.env.example +17 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/envs/production.env.example +17 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/envs/staging.env.example +17 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/tenants/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/tenants/template.env.example +8 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/README.md +26 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/agent.md +7 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/developers/dev-1.md +20 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/linux.md +9 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/macos.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/shared.md +19 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/windows.md +14 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/HOSTING/README.md +25 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/HOSTING/_template.md +41 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/HOSTING/hosting-1.md +41 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/README.md +21 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/RUNBOOK/README.md +15 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/RUNBOOK/deployment.md +19 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/RUNBOOK/disaster-recovery.md +15 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/RUNBOOK/ops-tasks.md +14 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/features/README.md +16 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/project-skills.md +146 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/research/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/research/software-compliance-research.md +269 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/working-with-agents.md +260 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/AGENTS.md +38 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/ARCHITECTURE.md +36 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/BEST_PRACTICES.md +27 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/CI_CD.md +23 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/FEATURES.md +15 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/README.md +22 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/RULES.md +37 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/STRUCTURE.md +45 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/TECH_STACK.md +28 -0
- package/.agents/skills/nsr-compliance/assets/nsr/scaffold-spec.md +63 -0
- package/.agents/skills/nsr-compliance/assets/nsr/scripts/scaffold.sh +103 -0
- package/.agents/skills/nsr-compliance/assets/nsr/scripts/validate.sh +52 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/SKILL.md +71 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/config/core_four.yaml +16 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/gates/check_danger.sh +102 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/gates/check_wiring.sh +69 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/gates/validate_code.sh +29 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/gates/verify_docs.py +66 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/generate.sh +109 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/harness/envelopes/result_envelope.json +14 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/harness/envelopes/task_envelope.json +20 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/harness/runner.py +303 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/telemetry/logger.py +112 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/README.md +18 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/config/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/gates/README.md +12 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/gates/check_env.sh +23 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/gates/check_paths.sh +20 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/gates/check_platform.sh +23 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/harness/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/harness/envelopes/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/installer/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/installer/install.sh +125 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/telemetry/README.md +11 -0
- package/.agents/skills/pr-ops/README.md +3 -0
- package/.agents/skills/pr-ops/SKILL.md +109 -0
- package/.agents/skills/ratatoskr-a2a/README.md +3 -0
- package/.agents/skills/ratatoskr-a2a/SKILL.md +148 -0
- package/.agents/skills/rules-check-drift/SKILL.md +81 -0
- package/.agents/skills/saga-bearings/README.md +3 -0
- package/.agents/skills/saga-bearings/SKILL.md +26 -0
- package/.agents/skills/saga-bearings/assets/bearings.md +161 -0
- package/.agents/skills/saga-bearings/assets/board-template.html +731 -0
- package/.agents/skills/saga-bearings/assets/recap.md +56 -0
- package/.agents/skills/syn-recovery/README.md +3 -0
- package/.agents/skills/syn-recovery/SKILL.md +54 -0
- package/.agents/skills/tyr-check/README.md +3 -0
- package/.agents/skills/tyr-check/SKILL.md +218 -0
- package/.agents/skills/urdh-hold/README.md +3 -0
- package/.agents/skills/urdh-hold/SKILL.md +25 -0
- package/.agents/skills/urdh-hold/assets/decisions.md +15 -0
- package/.agents/skills/urdh-hold/assets/hold.md +54 -0
- package/.agents/skills/vor-diagnostics/README.md +3 -0
- package/.agents/skills/vor-diagnostics/SKILL.md +68 -0
- package/.agents/skills/ymir-host/README.md +3 -0
- package/.agents/skills/ymir-host/SKILL.md +34 -0
- package/.agents/skills/ymir-host/assets/desktop.md +36 -0
- package/.agents/skills/ymir-host/assets/omarchy.md +297 -0
- package/.agents/skills/ymir-host/assets/runbooks.md +15 -0
- package/.agents/skills/ymir-host/assets/thjazi.md +220 -0
- package/.agents/skills/ymir-host/assets/update.md +64 -0
- package/.agents/tests/assets/board-render-harness.mjs +117 -0
- package/.agents/tests/cmux-test-safety.sh +51 -0
- package/.agents/tests/fixtures.sh +291 -0
- package/.agents/tests/fm-afk-inject-e2e.test.sh +428 -0
- package/.agents/tests/fm-afk-inject-herdr-e2e.test.sh +536 -0
- package/.agents/tests/fm-afk-launch.test.sh +961 -0
- package/.agents/tests/fm-afk-pi-herdr-return-e2e.test.sh +297 -0
- package/.agents/tests/fm-afk-return.test.sh +283 -0
- package/.agents/tests/fm-arm-pretool-check.test.sh +482 -0
- package/.agents/tests/fm-ask-user-authority.test.sh +42 -0
- package/.agents/tests/fm-backend-autodetect-smoke.test.sh +176 -0
- package/.agents/tests/fm-backend-cmux-smoke.test.sh +188 -0
- package/.agents/tests/fm-backend-cmux.test.sh +1166 -0
- package/.agents/tests/fm-backend-herdr-eventwait-smoke.test.sh +136 -0
- package/.agents/tests/fm-backend-herdr-eventwait.test.py +106 -0
- package/.agents/tests/fm-backend-herdr-focus-flash-e2e.test.sh +409 -0
- package/.agents/tests/fm-backend-herdr-launcher-workspace-e2e.test.sh +437 -0
- package/.agents/tests/fm-backend-herdr-presentation-e2e.test.sh +1424 -0
- package/.agents/tests/fm-backend-herdr-prune-safety-e2e.test.sh +180 -0
- package/.agents/tests/fm-backend-herdr-respawn-idem-e2e.test.sh +182 -0
- package/.agents/tests/fm-backend-herdr-smoke.test.sh +355 -0
- package/.agents/tests/fm-backend-herdr-workspace-per-home-e2e.test.sh +251 -0
- package/.agents/tests/fm-backend-herdr.test.sh +4606 -0
- package/.agents/tests/fm-backend-orca.test.sh +1357 -0
- package/.agents/tests/fm-backend-tmux-smoke.test.sh +173 -0
- package/.agents/tests/fm-backend-zellij-smoke.test.sh +205 -0
- package/.agents/tests/fm-backend-zellij.test.sh +1360 -0
- package/.agents/tests/fm-backend.test.sh +1142 -0
- package/.agents/tests/fm-backlog-atomicity.test.sh +2302 -0
- package/.agents/tests/fm-backlog-handoff.test.sh +1360 -0
- package/.agents/tests/fm-bearings-board-render.test.sh +135 -0
- package/.agents/tests/fm-bearings-board.test.sh +414 -0
- package/.agents/tests/fm-bearings-snapshot.test.sh +1990 -0
- package/.agents/tests/fm-bootstrap-network-parallel.test.sh +316 -0
- package/.agents/tests/fm-bootstrap.test.sh +1178 -0
- package/.agents/tests/fm-branch-supervision.test.sh +552 -0
- package/.agents/tests/fm-brief.test.sh +785 -0
- package/.agents/tests/fm-busy-adapter-wiring.test.sh +324 -0
- package/.agents/tests/fm-busy-state.test.sh +465 -0
- package/.agents/tests/fm-calm-pi-extension.test.sh +3979 -0
- package/.agents/tests/fm-captain-hold-lifecycle.test.sh +1187 -0
- package/.agents/tests/fm-cd-pretool-check.test.sh +400 -0
- package/.agents/tests/fm-check-unregister.test.sh +198 -0
- package/.agents/tests/fm-classify-corr-token.test.sh +543 -0
- package/.agents/tests/fm-classify-decision-key.test.sh +340 -0
- package/.agents/tests/fm-claude-stop-autoarm-live-e2e.test.sh +164 -0
- package/.agents/tests/fm-claude-stop-autoarm.test.sh +1190 -0
- package/.agents/tests/fm-cmux-claude-composer-live-e2e.test.sh +110 -0
- package/.agents/tests/fm-codex-continuity-live-e2e.test.sh +55 -0
- package/.agents/tests/fm-composer-ghost.test.sh +716 -0
- package/.agents/tests/fm-composer-lib.test.sh +666 -0
- package/.agents/tests/fm-composer-matrix-live-e2e.test.sh +220 -0
- package/.agents/tests/fm-control-herdr-smoke.test.sh +149 -0
- package/.agents/tests/fm-control-relaunch.test.sh +1530 -0
- package/.agents/tests/fm-control.test.sh +910 -0
- package/.agents/tests/fm-crew-state.test.sh +1610 -0
- package/.agents/tests/fm-cursor-harness.test.sh +404 -0
- package/.agents/tests/fm-cursor-primary-live-e2e.test.sh +217 -0
- package/.agents/tests/fm-cursor-primary.test.sh +708 -0
- package/.agents/tests/fm-daemon.test.sh +2740 -0
- package/.agents/tests/fm-documentation-audiences.test.sh +141 -0
- package/.agents/tests/fm-ensure-agents-md.test.sh +371 -0
- package/.agents/tests/fm-extension-binding.test.sh +2187 -0
- package/.agents/tests/fm-fleet-snapshot-view.test.sh +816 -0
- package/.agents/tests/fm-fleet-sync.test.sh +721 -0
- package/.agents/tests/fm-gate-refuse.test.sh +356 -0
- package/.agents/tests/fm-gitignore-config.test.sh +89 -0
- package/.agents/tests/fm-gotmp.test.sh +230 -0
- package/.agents/tests/fm-grok-continuity-live-e2e.test.sh +112 -0
- package/.agents/tests/fm-grok-harness.test.sh +117 -0
- package/.agents/tests/fm-grok-stop-live-e2e.test.sh +219 -0
- package/.agents/tests/fm-guard-stale-banner.test.sh +709 -0
- package/.agents/tests/fm-harness-adapter-instructions-live-e2e.test.sh +134 -0
- package/.agents/tests/fm-harness-adapter-references.test.sh +30 -0
- package/.agents/tests/fm-harness-liveness-drift-live-e2e.test.sh +151 -0
- package/.agents/tests/fm-herdr-lab.test.sh +243 -0
- package/.agents/tests/fm-herdr-session-cleanup-e2e.test.sh +146 -0
- package/.agents/tests/fm-herdr-session-cleanup.test.sh +329 -0
- package/.agents/tests/fm-herdr-submit-confirm-live-e2e.test.sh +125 -0
- package/.agents/tests/fm-herdr-version-floor-live-e2e.test.sh +144 -0
- package/.agents/tests/fm-home-summary-refresh.test.sh +971 -0
- package/.agents/tests/fm-inactive-reconcile.test.sh +485 -0
- package/.agents/tests/fm-kimi-harness.test.sh +687 -0
- package/.agents/tests/fm-lint-workflows.test.sh +532 -0
- package/.agents/tests/fm-lint.test.sh +1023 -0
- package/.agents/tests/fm-muse-harness.test.sh +932 -0
- package/.agents/tests/fm-muse-signals-live-e2e.test.sh +205 -0
- package/.agents/tests/fm-no-mistakes-required.test.sh +72 -0
- package/.agents/tests/fm-on.test.sh +507 -0
- package/.agents/tests/fm-opencode-primary-live-e2e.test.sh +357 -0
- package/.agents/tests/fm-operational-input.test.sh +160 -0
- package/.agents/tests/fm-peek-remote.test.sh +110 -0
- package/.agents/tests/fm-pending-reply.test.sh +1288 -0
- package/.agents/tests/fm-pi-branch-extension.test.sh +3182 -0
- package/.agents/tests/fm-pi-branch-live-e2e.test.sh +527 -0
- package/.agents/tests/fm-pi-primary-live-e2e.test.sh +345 -0
- package/.agents/tests/fm-pi-primary-types.test.sh +68 -0
- package/.agents/tests/fm-pi-watch-extension.test.sh +2843 -0
- package/.agents/tests/fm-pr-check-security.test.sh +2140 -0
- package/.agents/tests/fm-pr-merge.test.sh +2135 -0
- package/.agents/tests/fm-procevent-quota.test.sh +225 -0
- package/.agents/tests/fm-procevent-when.test.sh +406 -0
- package/.agents/tests/fm-procevent.test.sh +1745 -0
- package/.agents/tests/fm-project-origin.test.sh +110 -0
- package/.agents/tests/fm-public-followup.test.sh +2272 -0
- package/.agents/tests/fm-quota-array-dispatch-live-e2e.test.sh +526 -0
- package/.agents/tests/fm-quota-choose.test.sh +626 -0
- package/.agents/tests/fm-remote-backlog-handoff.test.sh +453 -0
- package/.agents/tests/fm-remote-doctor.test.sh +625 -0
- package/.agents/tests/fm-remote-entrypoint.test.sh +59 -0
- package/.agents/tests/fm-remote-job-orphan-reap.test.sh +205 -0
- package/.agents/tests/fm-remote-job.test.sh +768 -0
- package/.agents/tests/fm-remote-reply.test.sh +520 -0
- package/.agents/tests/fm-remote-secondmate-lifecycle-e2e.test.sh +1256 -0
- package/.agents/tests/fm-remote-secondmate-parent-binding.test.sh +326 -0
- package/.agents/tests/fm-remote-secondmate-trace-context.test.sh +310 -0
- package/.agents/tests/fm-remote-transport-lanes.test.sh +431 -0
- package/.agents/tests/fm-review-diff.test.sh +176 -0
- package/.agents/tests/fm-secondmate-harness.test.sh +2600 -0
- package/.agents/tests/fm-secondmate-lifecycle-e2e.test.sh +259 -0
- package/.agents/tests/fm-secondmate-liveness.test.sh +559 -0
- package/.agents/tests/fm-secondmate-reconcile.test.sh +732 -0
- package/.agents/tests/fm-secondmate-safety.test.sh +2972 -0
- package/.agents/tests/fm-secondmate-sync.test.sh +913 -0
- package/.agents/tests/fm-send-inbox-doorbell-live-e2e.test.sh +206 -0
- package/.agents/tests/fm-send-inbox.test.sh +352 -0
- package/.agents/tests/fm-send-popup-settle.test.sh +167 -0
- package/.agents/tests/fm-send-remote-delivery.test.sh +796 -0
- package/.agents/tests/fm-send-resolve-key.test.sh +551 -0
- package/.agents/tests/fm-send-secondmate-marker-herdr-e2e.test.sh +187 -0
- package/.agents/tests/fm-send-secondmate-marker.test.sh +278 -0
- package/.agents/tests/fm-send-settle.test.sh +147 -0
- package/.agents/tests/fm-send-strict.test.sh +241 -0
- package/.agents/tests/fm-session-lock-ancestry.test.sh +365 -0
- package/.agents/tests/fm-session-start.test.sh +2515 -0
- package/.agents/tests/fm-sessionstart-hook-live-e2e.test.sh +631 -0
- package/.agents/tests/fm-sessionstart-instruction-refresh-live-e2e.test.sh +230 -0
- package/.agents/tests/fm-sessionstart-nudge.test.sh +1039 -0
- package/.agents/tests/fm-shared-captain-inheritance.test.sh +404 -0
- package/.agents/tests/fm-spawn-batch.test.sh +148 -0
- package/.agents/tests/fm-spawn-dispatch-profile.test.sh +827 -0
- package/.agents/tests/fm-spawn-pool-base-freshen.test.sh +440 -0
- package/.agents/tests/fm-spawn-worktree-settle.test.sh +147 -0
- package/.agents/tests/fm-startup-memory-budget.test.sh +333 -0
- package/.agents/tests/fm-startup-network.test.sh +712 -0
- package/.agents/tests/fm-stow-cascade.test.sh +370 -0
- package/.agents/tests/fm-subagent-pretool-check.test.sh +291 -0
- package/.agents/tests/fm-supervision-events.test.sh +156 -0
- package/.agents/tests/fm-supervision-instructions.test.sh +189 -0
- package/.agents/tests/fm-tangle-guard.test.sh +277 -0
- package/.agents/tests/fm-task-delivery.test.sh +420 -0
- package/.agents/tests/fm-task-inbox.test.sh +513 -0
- package/.agents/tests/fm-teardown-endpoint-safety.test.sh +374 -0
- package/.agents/tests/fm-teardown.test.sh +2665 -0
- package/.agents/tests/fm-test-fixture-cleanup.test.sh +172 -0
- package/.agents/tests/fm-test-fixtures.test.sh +132 -0
- package/.agents/tests/fm-test-isolation-proof.test.sh +278 -0
- package/.agents/tests/fm-test-run.test.sh +1196 -0
- package/.agents/tests/fm-tmux-agent-liveness.test.sh +354 -0
- package/.agents/tests/fm-tmux-submit-busy.test.sh +340 -0
- package/.agents/tests/fm-tool-update-check.test.sh +1044 -0
- package/.agents/tests/fm-trace-context-lib.test.sh +253 -0
- package/.agents/tests/fm-trace-context-spawn.test.sh +581 -0
- package/.agents/tests/fm-transition-lib.test.sh +54 -0
- package/.agents/tests/fm-turnend-guard.test.sh +1822 -0
- package/.agents/tests/fm-update.test.sh +304 -0
- package/.agents/tests/fm-vendor-auth-probe.test.sh +395 -0
- package/.agents/tests/fm-voice-relay.test.sh +4741 -0
- package/.agents/tests/fm-wake-daemon-lifecycle-e2e.test.sh +171 -0
- package/.agents/tests/fm-wake-drain-open-decisions-cursor.test.sh +356 -0
- package/.agents/tests/fm-wake-drain-open-decisions.test.sh +226 -0
- package/.agents/tests/fm-wake-drain-unread-status.test.sh +379 -0
- package/.agents/tests/fm-wake-queue.test.sh +1224 -0
- package/.agents/tests/fm-watch-arm.test.sh +821 -0
- package/.agents/tests/fm-watch-checkpoint.test.sh +87 -0
- package/.agents/tests/fm-watch-recovery-loop.test.sh +223 -0
- package/.agents/tests/fm-watch-triage.test.sh +3889 -0
- package/.agents/tests/fm-watcher-lock.test.sh +1133 -0
- package/.agents/tests/fm-x-mode.test.sh +3042 -0
- package/.agents/tests/gleipnir-guard-pretool-check.test.sh +51 -0
- package/.agents/tests/gleipnir-machine-lock.test.sh +130 -0
- package/.agents/tests/herdr-test-safety.sh +42 -0
- package/.agents/tests/lib.sh +315 -0
- package/.agents/tests/remote-herdr-fixture.sh +125 -0
- package/.agents/tests/secondmate-helpers.sh +193 -0
- package/.agents/tests/smoke.test.sh +93 -0
- package/.agents/tests/wake-helpers.sh +338 -0
- package/.agents/tests/zellij-test-safety.sh +60 -0
- package/.agents/tools/README.md +10 -0
- package/.agents/tools/bin/tasks-cli +267 -0
- package/.agents/tools/tasks-cli.ts +216 -0
- package/AGENTS.md +454 -0
- package/CHANGELOG.md +881 -0
- package/LICENSE +1 -1
- package/NOTICE +63 -0
- package/README.md +113 -59
- package/RULES/01-domains.md +51 -0
- package/RULES/02-agents.md +78 -0
- package/RULES/03-houses.md +61 -0
- package/RULES/04-hoard.md +65 -0
- package/RULES/05-platforms.md +67 -0
- package/RULES/06-append-only.md +58 -0
- package/RULES/07-config.md +45 -0
- package/RULES/08-delivery-gate.md +75 -0
- package/RULES/README.md +20 -0
- package/bin/README.md +107 -0
- package/bin/a2a-mcp.sh +98 -0
- package/bin/a2a-serve.py +103 -0
- package/bin/a2a-serve.sh +8 -0
- package/bin/a2a-talk.sh +50 -0
- package/bin/a2abridge-ensure.sh +108 -0
- package/bin/agent-run.sh +43 -0
- package/bin/agents-config.sh +233 -0
- package/bin/apodex-smoke-test.sh +92 -0
- package/bin/bifrost-bridge.sh +112 -0
- package/bin/bifrost-ingress.sh +77 -0
- package/bin/bootstrap-macos.sh +107 -0
- package/bin/bootstrap-windows.ps1 +112 -0
- package/bin/branch-guard.sh +64 -0
- package/bin/brokk +73 -0
- package/bin/brokk-classify-lib.sh +1770 -0
- package/bin/brokk-lease-lib.sh +222 -0
- package/bin/brokk-lease.sh +193 -0
- package/bin/brokk-lint.sh +65 -0
- package/bin/brokk-send.sh +38 -0
- package/bin/brokk-update.sh +9 -0
- package/bin/brokk-wake-grant.sh +127 -0
- package/bin/brokk-wake-lib.sh +1849 -0
- package/bin/changelog-guard.sh +165 -0
- package/bin/crash-sense.sh +160 -0
- package/bin/desktop-place.sh +224 -0
- package/bin/docs-guard.sh +39 -0
- package/bin/editor-place.sh +207 -0
- package/bin/eindri-acclaim.sh +34 -0
- package/bin/eindri-control.sh +28 -0
- package/bin/eindri-role.sh +83 -0
- package/bin/eindri-seen.sh +41 -0
- package/bin/eindri-send.sh +15 -0
- package/bin/eindri-start.sh +85 -0
- package/bin/eindri-watch.sh +57 -0
- package/bin/einherjar-spawn.sh +576 -0
- package/bin/eir-doctor.sh +112 -0
- package/bin/erindi-brief.sh +271 -0
- package/bin/fleet-apply.sh +68 -0
- package/bin/github-deploy.sh +81 -0
- package/bin/gjallarhorn-expose.sh +102 -0
- package/bin/gjallarhorn-notify.sh +58 -0
- package/bin/gjallarhorn-purge.sh +54 -0
- package/bin/gjallarhorn-tunnel.sh +72 -0
- package/bin/gleipnir-lock-lib.sh +284 -0
- package/bin/groa-update.sh +122 -0
- package/bin/hall-snapshot.sh +92 -0
- package/bin/hamr-harness.sh +246 -0
- package/bin/heimdall-ssh-keys.sh +374 -0
- package/bin/herdr-agents.py +44 -0
- package/bin/herdr-ensure.sh +104 -0
- package/bin/herdr-run.sh +431 -0
- package/bin/hermes-ensure.sh +88 -0
- package/bin/hoard-lib.sh +25 -0
- package/bin/hodd.sh +78 -0
- package/bin/host-sense.sh +199 -0
- package/bin/huginn-research-worker.sh +108 -0
- package/bin/local-model-lock.sh +51 -0
- package/bin/mimir-bridge.py +226 -0
- package/bin/mimir-bridge.sh +87 -0
- package/bin/mimir-ingest.sh +131 -0
- package/bin/mimir.sh +113 -0
- package/bin/mjollnir-webhook.sh +59 -0
- package/bin/mjollnir.sh +85 -0
- package/bin/model-hardware.sh +82 -0
- package/bin/model-resolve.sh +147 -0
- package/bin/models-detect.sh +178 -0
- package/bin/nornir-cron-start.sh +162 -0
- package/bin/nornir-job-daily-briefing.sh +191 -0
- package/bin/nornir-job-git-sync.sh +152 -0
- package/bin/nornir-job-memory-housekeeping.sh +114 -0
- package/bin/nornir-job-observer.sh +166 -0
- package/bin/nornir-job-skillopt-sleep.sh +76 -0
- package/bin/omarchy-hook-install.sh +60 -0
- package/bin/omarchy-install.sh +148 -0
- package/bin/omarchy-plugins.sh +174 -0
- package/bin/omarchy-sense.sh +149 -0
- package/bin/perm-guard.sh +30 -0
- package/bin/pi-agent.sh +68 -0
- package/bin/pi-ensure.sh +77 -0
- package/bin/pi-local.sh +37 -0
- package/bin/pi-seat.sh +63 -0
- package/bin/prereq-ensure.sh +166 -0
- package/bin/private-guard.sh +38 -0
- package/bin/project-git.sh +55 -0
- package/bin/public-guard.sh +70 -0
- package/bin/ratatoskr.sh +49 -0
- package/bin/realm-lib.sh +32 -0
- package/bin/repo-scrub.sh +62 -0
- package/bin/rodd-operational-input.sh +250 -0
- package/bin/runes-append.sh +198 -0
- package/bin/saga-session-start.sh +172 -0
- package/bin/saga-sessionstart-run.sh +79 -0
- package/bin/saga-wake-drain.sh +41 -0
- package/bin/secret-guard.sh +63 -0
- package/bin/sessrumnir-ensure.sh +100 -0
- package/bin/sessrumnir-sync.sh +237 -0
- package/bin/sessrumnir.sh +91 -0
- package/bin/skillopt-setup.sh +76 -0
- package/bin/skuld-branch-outcome.sh +203 -0
- package/bin/skuld-branch-prompt.sh +101 -0
- package/bin/smidja-bootstrap.sh +90 -0
- package/bin/smidja-observe.sh +86 -0
- package/bin/syn-arm-pretool-check.sh +57 -0
- package/bin/syn-asset-pretool-check.sh +76 -0
- package/bin/syn-cd-pretool-check.sh +28 -0
- package/bin/syn-guard-pretool-check.sh +83 -0
- package/bin/syn-turnend-guard.sh +36 -0
- package/bin/syn-watch-arm.sh +99 -0
- package/bin/tailscale-sync.sh +190 -0
- package/bin/telegram-bot.sh +69 -0
- package/bin/toolchain.sh +74 -0
- package/bin/utgard.sh +111 -0
- package/bin/valhalla.sh +115 -0
- package/bin/valknut-load.sh +260 -0
- package/bin/vor-crew-state.sh +124 -0
- package/bin/wedge-notify.sh +47 -0
- package/bin/workspace-provision.sh +80 -0
- package/bin/workspace-rag.sh +150 -0
- package/bin/wyrd-db.sh +47 -0
- package/bin/yggdrasil.sh +152 -0
- package/bin/ymir-edit.sh +145 -0
- package/bin/ymir-install.sh +641 -0
- package/bin/ymir-invite.sh +93 -0
- package/bin/ymir-isolation.sh +88 -0
- package/bin/ymir-migrate.sh +61 -0
- package/bin/ymir-platform.sh +348 -0
- package/bin/ymir-say.sh +97 -0
- package/bin/ymir-setup-auth.sh +108 -0
- package/bin/ymir-validate.sh +173 -0
- package/bin/ymir.js +74 -16
- package/docs/Architecture.md +339 -0
- package/docs/design.md +351 -0
- package/docs/installations/README.md +63 -0
- package/docs/installations/ymir-home.md +93 -0
- package/docs/integration.md +105 -0
- package/docs/lore.md +1056 -0
- package/docs/research/agent-harnesses.md +290 -0
- package/docs/runbooks/README.md +19 -0
- package/docs/runbooks/a2a.md +91 -0
- package/docs/runbooks/agent-permissions.md +99 -0
- package/docs/runbooks/agents.md +57 -0
- package/docs/runbooks/models.md +69 -0
- package/docs/runbooks/realm-onboarding.md +60 -0
- package/docs/runbooks/secrets-and-hoard.md +60 -0
- package/docs/runbooks/updates-and-migrations.md +110 -0
- package/docs/runbooks/worktrees-isolation.md +72 -0
- package/docs/session-start.md +105 -0
- package/docs/skillopt-integration.md +321 -0
- package/docs/sync-system.md +66 -0
- package/docs/workspaces.md +104 -0
- package/docs/ymir-rut.md +260 -0
- package/package.json +44 -14
- package/packaging/build.sh +74 -0
- package/packaging/macos/Ymir Installer.command +43 -0
- package/packaging/windows/ymir-setup.nsi +74 -0
- package/scripts/README.md +22 -0
- package/scripts/electron.sh +210 -0
- package/scripts/start.sh +167 -0
- package/scripts/stop.sh +113 -0
- package/install.sh +0 -35
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# fm-timeout-lib.sh - the single owner of bounded command execution.
|
|
3
|
+
#
|
|
4
|
+
# Sourced, never executed. Provides one hard-bound runner so no caller has to
|
|
5
|
+
# re-derive the coreutils/BSD/perl selection, and so every bounded call in this
|
|
6
|
+
# repo agrees on what "the bound was hit" means.
|
|
7
|
+
#
|
|
8
|
+
# fm_timeout_mechanism
|
|
9
|
+
# Prints the mechanism fm_run_timed will use on this host: "timeout",
|
|
10
|
+
# "gtimeout", "perl", or "bash". Set FM_TIMEOUT_MECHANISM_OVERRIDE=bash
|
|
11
|
+
# to force the dependency-free fallback.
|
|
12
|
+
#
|
|
13
|
+
# fm_run_timed <seconds> <command> [args...]
|
|
14
|
+
# Runs the command with a hard bound. Exit status is the command's own,
|
|
15
|
+
# except 124, which means the bound was hit (GNU timeout's convention,
|
|
16
|
+
# reproduced by the perl and bash fallbacks).
|
|
17
|
+
#
|
|
18
|
+
# A non-positive bound is not a bound: `timeout 0` and the perl fallback's
|
|
19
|
+
# `alarm 0` both disable the deadline, so callers must reject 0 before calling.
|
|
20
|
+
#
|
|
21
|
+
# All four mechanisms terminate the whole process GROUP, not just the direct
|
|
22
|
+
# child, so a hung grandchild (a vendor CLI spawned by a wrapper script, a git
|
|
23
|
+
# fetch spawned by a sweep) cannot outlive the bound. GNU/BSD `timeout` does
|
|
24
|
+
# this by default because it does not run the command in the foreground process
|
|
25
|
+
# group; the perl fallback does it explicitly with setpgrp plus a negative pid,
|
|
26
|
+
# and the bash fallback uses monitor mode to give the bounded child its own
|
|
27
|
+
# process group before signaling its negative pid.
|
|
28
|
+
set -u
|
|
29
|
+
|
|
30
|
+
fm_timeout_mechanism() {
|
|
31
|
+
if [ "${FM_TIMEOUT_MECHANISM_OVERRIDE:-}" = bash ]; then
|
|
32
|
+
printf 'bash\n'
|
|
33
|
+
elif command -v timeout >/dev/null 2>&1; then
|
|
34
|
+
printf 'timeout\n'
|
|
35
|
+
elif command -v gtimeout >/dev/null 2>&1; then
|
|
36
|
+
printf 'gtimeout\n'
|
|
37
|
+
elif command -v perl >/dev/null 2>&1; then
|
|
38
|
+
printf 'perl\n'
|
|
39
|
+
else
|
|
40
|
+
printf 'bash\n'
|
|
41
|
+
fi
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
fm_run_bash_timeout() {
|
|
45
|
+
local seconds=$1 command_status deadline_status child_pid watchdog_pid command_rc recorded_rc monitor_was_on=0
|
|
46
|
+
shift
|
|
47
|
+
command_status=$(mktemp "${TMPDIR:-/tmp}/fm-bash-timeout-command.XXXXXX" 2>/dev/null) || return 124
|
|
48
|
+
deadline_status="${command_status}.deadline"
|
|
49
|
+
case $- in *m*) monitor_was_on=1 ;; esac
|
|
50
|
+
set -m
|
|
51
|
+
(
|
|
52
|
+
set +m
|
|
53
|
+
"$@"
|
|
54
|
+
command_rc=$?
|
|
55
|
+
printf '%s\n' "$command_rc" > "$command_status"
|
|
56
|
+
exit "$command_rc"
|
|
57
|
+
) &
|
|
58
|
+
child_pid=$!
|
|
59
|
+
(
|
|
60
|
+
set +m
|
|
61
|
+
sleep "$seconds"
|
|
62
|
+
printf 'expired\n' > "$deadline_status"
|
|
63
|
+
kill -TERM -- "-$child_pid" 2>/dev/null || true
|
|
64
|
+
sleep 0.2
|
|
65
|
+
kill -KILL -- "-$child_pid" 2>/dev/null || true
|
|
66
|
+
exit 124
|
|
67
|
+
) &
|
|
68
|
+
watchdog_pid=$!
|
|
69
|
+
[ "$monitor_was_on" -eq 1 ] || set +m
|
|
70
|
+
|
|
71
|
+
if wait "$child_pid" 2>/dev/null; then
|
|
72
|
+
command_rc=0
|
|
73
|
+
else
|
|
74
|
+
command_rc=$?
|
|
75
|
+
fi
|
|
76
|
+
if [ -s "$deadline_status" ]; then
|
|
77
|
+
wait "$watchdog_pid" 2>/dev/null || true
|
|
78
|
+
command_rc=124
|
|
79
|
+
else
|
|
80
|
+
kill -TERM -- "-$watchdog_pid" 2>/dev/null || kill "$watchdog_pid" 2>/dev/null || true
|
|
81
|
+
wait "$watchdog_pid" 2>/dev/null || true
|
|
82
|
+
recorded_rc=$(cat "$command_status" 2>/dev/null || true)
|
|
83
|
+
case "$recorded_rc" in ''|*[!0-9]*) ;; *) command_rc=$recorded_rc ;; esac
|
|
84
|
+
fi
|
|
85
|
+
rm -f "$command_status" "$deadline_status" 2>/dev/null || true
|
|
86
|
+
return "$command_rc"
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
fm_run_external_timeout() {
|
|
90
|
+
local runner=$1 seconds=$2 status_file runner_pid runner_rc command_rc
|
|
91
|
+
shift 2
|
|
92
|
+
status_file=$(mktemp "${TMPDIR:-/tmp}/fm-timeout-status.XXXXXX" 2>/dev/null) || return 124
|
|
93
|
+
# Run timeout asynchronously so its pid - also the process-group id created
|
|
94
|
+
# by GNU/BSD timeout without --foreground - remains available for cleanup.
|
|
95
|
+
# A shell wrapper can exit promptly on TERM while one of its descendants
|
|
96
|
+
# ignores TERM; timeout then considers the command finished and does not send
|
|
97
|
+
# its configured KILL. Explicitly reap that leftover group on a real timeout.
|
|
98
|
+
# shellcheck disable=SC2016 # Expansion is deliberately deferred to the child shell.
|
|
99
|
+
"$runner" -k 1 "$seconds" bash -c '
|
|
100
|
+
status_file=$1
|
|
101
|
+
shift
|
|
102
|
+
"$@"
|
|
103
|
+
command_rc=$?
|
|
104
|
+
printf "%s\n" "$command_rc" > "$status_file"
|
|
105
|
+
exit "$command_rc"
|
|
106
|
+
' _ "$status_file" "$@" &
|
|
107
|
+
runner_pid=$!
|
|
108
|
+
if wait "$runner_pid"; then
|
|
109
|
+
runner_rc=0
|
|
110
|
+
else
|
|
111
|
+
runner_rc=$?
|
|
112
|
+
fi
|
|
113
|
+
command_rc=$(cat "$status_file" 2>/dev/null || true)
|
|
114
|
+
rm -f "$status_file" 2>/dev/null || true
|
|
115
|
+
case "$command_rc" in
|
|
116
|
+
''|*[!0-9]*) ;;
|
|
117
|
+
*) [ "$command_rc" -le 255 ] && return "$command_rc" ;;
|
|
118
|
+
esac
|
|
119
|
+
case "$runner_rc" in
|
|
120
|
+
124|137)
|
|
121
|
+
kill -KILL -- "-$runner_pid" 2>/dev/null || true
|
|
122
|
+
return 124
|
|
123
|
+
;;
|
|
124
|
+
*) return "$runner_rc" ;;
|
|
125
|
+
esac
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
fm_run_timed() { # <seconds> <command...>
|
|
129
|
+
local seconds=$1
|
|
130
|
+
shift
|
|
131
|
+
case "$(fm_timeout_mechanism)" in
|
|
132
|
+
timeout) fm_run_external_timeout timeout "$seconds" "$@" ;;
|
|
133
|
+
gtimeout) fm_run_external_timeout gtimeout "$seconds" "$@" ;;
|
|
134
|
+
perl)
|
|
135
|
+
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)' \
|
|
136
|
+
"$seconds" "$@"
|
|
137
|
+
;;
|
|
138
|
+
bash) fm_run_bash_timeout "$seconds" "$@" ;;
|
|
139
|
+
*) return 124 ;;
|
|
140
|
+
esac
|
|
141
|
+
}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# fm-timing-lib.sh - the single owner of the deferred network stage's elapsed-time
|
|
3
|
+
# instrumentation.
|
|
4
|
+
#
|
|
5
|
+
# Sourced, never executed.
|
|
6
|
+
#
|
|
7
|
+
# WHY THIS EXISTS. The deferred stage (bin/fm-startup-network.sh) publishes one
|
|
8
|
+
# aggregate started/finished pair, so a run that took a minute could not be
|
|
9
|
+
# attributed to a phase, a host, or a clone without re-running it by hand under
|
|
10
|
+
# manual tracing. These helpers record per-step elapsed times as the run happens,
|
|
11
|
+
# so the next slow run is answerable from the durable record alone.
|
|
12
|
+
#
|
|
13
|
+
# OFF BY DEFAULT, AND INERT. Every helper is a no-op unless FM_TIMING_LOG names a
|
|
14
|
+
# file. Nothing here talks to the network, waits, locks, or changes control flow:
|
|
15
|
+
# a failed append is discarded rather than propagated, because losing a diagnostic
|
|
16
|
+
# line must never change what a sweep does or how it exits.
|
|
17
|
+
#
|
|
18
|
+
# ENVIRONMENT, both exported by the stage that owns a run:
|
|
19
|
+
# FM_TIMING_LOG append-only record file. Unset or empty disables recording.
|
|
20
|
+
# Exported across process boundaries on purpose: the phases
|
|
21
|
+
# being measured run in bin/fm-bootstrap.sh and
|
|
22
|
+
# bin/fm-fleet-sync.sh, which are children of the stage.
|
|
23
|
+
# FM_TIMING_EPOCH_MS the run's start instant, so every record carries an offset
|
|
24
|
+
# from ONE origin even though the records are written by
|
|
25
|
+
# several processes. Defaults to the first recording
|
|
26
|
+
# process's own start, which keeps a hand-run child readable.
|
|
27
|
+
#
|
|
28
|
+
# RECORD FORMAT, one tab-separated line per measured step:
|
|
29
|
+
# v1 <TAB> scope <TAB> name <TAB> start-offset-ms <TAB> elapsed-ms <TAB> detail
|
|
30
|
+
# Appends are single short lines opened O_APPEND, so concurrent writers interleave
|
|
31
|
+
# whole lines rather than corrupting each other.
|
|
32
|
+
#
|
|
33
|
+
# NO SECRETS, BY CONSTRUCTION. `detail` names an identity - a secondmate id, a
|
|
34
|
+
# host, a clone directory name - and identities never contain whitespace, while
|
|
35
|
+
# the things that must never reach this file (a command line, an environment
|
|
36
|
+
# dump, a captured error) always do. So a detail carrying ANY whitespace is not a
|
|
37
|
+
# truncated identity, it is free text that arrived from somewhere it should not
|
|
38
|
+
# have, and it is dropped entirely rather than cleaned up: cleaning would leave
|
|
39
|
+
# the token in `KEY=secret` behind, because a credential is made of exactly the
|
|
40
|
+
# characters an identity is made of. What remains is then narrowed to
|
|
41
|
+
# [A-Za-z0-9._@:/+-] and truncated, which is what stops a detail from forging
|
|
42
|
+
# extra tab-separated records. Enforcing this here rather than at each call site
|
|
43
|
+
# is what makes "this file cannot carry a credential or an argv" checkable in one
|
|
44
|
+
# place.
|
|
45
|
+
set -u
|
|
46
|
+
|
|
47
|
+
FM_TIMING_DETAIL_MAX=${FM_TIMING_DETAIL_MAX:-80}
|
|
48
|
+
|
|
49
|
+
fm_timing_enabled() {
|
|
50
|
+
[ -n "${FM_TIMING_LOG:-}" ]
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
# Milliseconds since the epoch. EPOCHREALTIME is a bash builtin (no fork) whose
|
|
54
|
+
# decimal separator follows the locale, so both forms are accepted. A shell
|
|
55
|
+
# without it - macOS's system bash 3.2, which `env bash` still resolves to on a
|
|
56
|
+
# host with no newer bash on PATH - degrades to whole-second granularity rather
|
|
57
|
+
# than losing the timing entirely. That is a coarser answer to "which host was
|
|
58
|
+
# slow", not a missing one, because the steps being measured are seconds-scale.
|
|
59
|
+
fm_timing_now_ms() {
|
|
60
|
+
local raw sec frac
|
|
61
|
+
raw=${EPOCHREALTIME:-}
|
|
62
|
+
case "$raw" in
|
|
63
|
+
*[0-9][.,][0-9]*)
|
|
64
|
+
sec=${raw%%[.,]*}
|
|
65
|
+
frac=${raw#*[.,]}
|
|
66
|
+
frac="${frac}000"
|
|
67
|
+
frac=${frac:0:3}
|
|
68
|
+
case "$sec$frac" in
|
|
69
|
+
''|*[!0-9]*) ;;
|
|
70
|
+
*) printf '%s\n' "$(( sec * 1000 + 10#$frac ))"; return 0 ;;
|
|
71
|
+
esac
|
|
72
|
+
;;
|
|
73
|
+
esac
|
|
74
|
+
sec=$(date +%s 2>/dev/null || printf '0')
|
|
75
|
+
case "$sec" in ''|*[!0-9]*) sec=0 ;; esac
|
|
76
|
+
printf '%s\n' "$(( sec * 1000 ))"
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
# Ensure FM_TIMING_EPOCH_MS holds the origin every offset is measured from.
|
|
80
|
+
# Callers that own a run export it up front; a process that starts recording
|
|
81
|
+
# without one adopts its own first measurement so its records stay internally
|
|
82
|
+
# consistent instead of being silently dropped.
|
|
83
|
+
#
|
|
84
|
+
# This SETS the variable rather than printing it, because the caller must read it
|
|
85
|
+
# as "$FM_TIMING_EPOCH_MS" and not through a command substitution: a substitution
|
|
86
|
+
# runs in a subshell, so the lazily chosen origin would be discarded and every
|
|
87
|
+
# record would recompute it, flattening every start offset to zero.
|
|
88
|
+
fm_timing_epoch_ensure() {
|
|
89
|
+
case "${FM_TIMING_EPOCH_MS:-}" in
|
|
90
|
+
''|*[!0-9]*)
|
|
91
|
+
FM_TIMING_EPOCH_MS=$(fm_timing_now_ms)
|
|
92
|
+
export FM_TIMING_EPOCH_MS
|
|
93
|
+
;;
|
|
94
|
+
esac
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
# Start a run: point recording at <file> and stamp the shared origin. The file is
|
|
98
|
+
# created empty so a run that dies before its first record still publishes an
|
|
99
|
+
# empty-but-present artifact rather than looking like it was never instrumented.
|
|
100
|
+
fm_timing_start() { # <file>
|
|
101
|
+
local file=$1
|
|
102
|
+
[ -n "$file" ] || return 0
|
|
103
|
+
: > "$file" 2>/dev/null || return 0
|
|
104
|
+
FM_TIMING_LOG=$file
|
|
105
|
+
FM_TIMING_EPOCH_MS=$(fm_timing_now_ms)
|
|
106
|
+
export FM_TIMING_LOG FM_TIMING_EPOCH_MS
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
fm_timing_sanitize() { # <text>
|
|
110
|
+
local text=${1:-}
|
|
111
|
+
case "$text" in
|
|
112
|
+
*[[:space:]]*) printf '%s\n' 'unrecordable'; return 0 ;;
|
|
113
|
+
esac
|
|
114
|
+
text=${text//[!A-Za-z0-9._@:\/+-]/_}
|
|
115
|
+
printf '%s\n' "${text:0:$FM_TIMING_DETAIL_MAX}"
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
# Record one measured step. Never fails the caller: a missing log, an unwritable
|
|
119
|
+
# path, or a malformed start stamp all resolve to "no record", never an error.
|
|
120
|
+
fm_timing_record() { # <scope> <name> <start-ms> [detail]
|
|
121
|
+
local scope=$1 name=$2 start=$3 detail=${4:-} now offset elapsed
|
|
122
|
+
fm_timing_enabled || return 0
|
|
123
|
+
case "$start" in ''|*[!0-9]*) return 0 ;; esac
|
|
124
|
+
now=$(fm_timing_now_ms)
|
|
125
|
+
fm_timing_epoch_ensure
|
|
126
|
+
offset=$(( start - FM_TIMING_EPOCH_MS ))
|
|
127
|
+
[ "$offset" -ge 0 ] || offset=0
|
|
128
|
+
elapsed=$(( now - start ))
|
|
129
|
+
[ "$elapsed" -ge 0 ] || elapsed=0
|
|
130
|
+
printf 'v1\t%s\t%s\t%s\t%s\t%s\n' \
|
|
131
|
+
"$(fm_timing_sanitize "$scope")" "$(fm_timing_sanitize "$name")" \
|
|
132
|
+
"$offset" "$elapsed" "$(fm_timing_sanitize "$detail")" \
|
|
133
|
+
>> "$FM_TIMING_LOG" 2>/dev/null || true
|
|
134
|
+
return 0
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
# Render a recorded run for a human. Prints nothing at all when the file is
|
|
138
|
+
# missing or holds no record, so an uninstrumented or empty run adds no output.
|
|
139
|
+
fm_timing_render() { # <file>
|
|
140
|
+
local file=$1
|
|
141
|
+
[ -n "$file" ] && [ -s "$file" ] || return 0
|
|
142
|
+
awk -F'\t' '
|
|
143
|
+
$1 != "v1" || NF < 5 { next }
|
|
144
|
+
{
|
|
145
|
+
records++
|
|
146
|
+
scope[records] = $2; name[records] = $3
|
|
147
|
+
offset[records] = $4 + 0; elapsed[records] = $5 + 0
|
|
148
|
+
detail[records] = $6
|
|
149
|
+
}
|
|
150
|
+
END {
|
|
151
|
+
if (records == 0) exit 0
|
|
152
|
+
print "TIMINGS - where the deferred network checks spent their time (ms):"
|
|
153
|
+
for (i = 1; i <= records; i++) {
|
|
154
|
+
label = name[i]
|
|
155
|
+
if (detail[i] != "") label = label " " detail[i]
|
|
156
|
+
printf " %-11s %-42s start=+%-7d elapsed=%d\n", scope[i], label, offset[i], elapsed[i]
|
|
157
|
+
}
|
|
158
|
+
for (i = 1; i <= records; i++) {
|
|
159
|
+
for (j = i + 1; j <= records; j++) {
|
|
160
|
+
if (elapsed[j] > elapsed[i]) {
|
|
161
|
+
t = scope[i]; scope[i] = scope[j]; scope[j] = t
|
|
162
|
+
t = name[i]; name[i] = name[j]; name[j] = t
|
|
163
|
+
t = offset[i]; offset[i] = offset[j]; offset[j] = t
|
|
164
|
+
t = elapsed[i]; elapsed[i] = elapsed[j]; elapsed[j] = t
|
|
165
|
+
t = detail[i]; detail[i] = detail[j]; detail[j] = t
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
top = records < 3 ? records : 3
|
|
170
|
+
line = ""
|
|
171
|
+
for (i = 1; i <= top; i++) {
|
|
172
|
+
label = name[i]
|
|
173
|
+
if (detail[i] != "") label = label " " detail[i]
|
|
174
|
+
line = line (line == "" ? "" : ", ") scope[i] " " label " " elapsed[i] "ms"
|
|
175
|
+
}
|
|
176
|
+
print " slowest: " line
|
|
177
|
+
}
|
|
178
|
+
' "$file" 2>/dev/null || true
|
|
179
|
+
}
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# fm-tmux-lib.sh — shared tmux pane primitives for firstmate.
|
|
3
|
+
#
|
|
4
|
+
# ONE tmux source for delivery-busy detection, composer capture primitives,
|
|
5
|
+
# and verified submit.
|
|
6
|
+
# Both the away-mode daemon and bin/fm-send.sh reach these primitives through
|
|
7
|
+
# backend dispatch, while bin/fm-composer-lib.sh owns the shared verdict.
|
|
8
|
+
#
|
|
9
|
+
# Composer shapes and verdicts are owned by bin/fm-composer-lib.sh.
|
|
10
|
+
# This file owns only tmux's styled capture, cursor and Pi identity primitives,
|
|
11
|
+
# delivery busy read, and submit conversions that consume the shared verdict.
|
|
12
|
+
# Styled captures remain internal; fm-peek and every human-facing capture stay
|
|
13
|
+
# plain.
|
|
14
|
+
#
|
|
15
|
+
# OpenCode's busy-queued Enter conversion accepts only structurally proven
|
|
16
|
+
# pending text after retries, while the separate turn-started conversion accepts
|
|
17
|
+
# an unknown post-Enter composer only after this submit observed an idle baseline
|
|
18
|
+
# become busy.
|
|
19
|
+
# The queued-Enter policy itself lives in fm_composer_queued_enter_verdict
|
|
20
|
+
# (bin/fm-composer-lib.sh); this file supplies tmux's pane-busy primitive.
|
|
21
|
+
#
|
|
22
|
+
# FM_COMPOSER_IDLE_RE is interpreted by the shared classifier with its structural
|
|
23
|
+
# and styling safety gates.
|
|
24
|
+
# FM_BUSY_REGEX overrides the rendered delivery-busy matching used here.
|
|
25
|
+
#
|
|
26
|
+
# NOT a task-state source: task busy state is owned by bin/fm-busy-lib.sh's
|
|
27
|
+
# semantic contract. The matching below serves only delivery guards: the submit
|
|
28
|
+
# acknowledgement and the away-mode supervisor-pane busy guard. Both ask about
|
|
29
|
+
# the pane receiving input, not the state of a recorded worker task. Matching
|
|
30
|
+
# stays harness-scoped so one harness's output cannot make another read busy.
|
|
31
|
+
#
|
|
32
|
+
# All functions are `set -u` and `set -e` safe (guarded tmux calls, explicit
|
|
33
|
+
# returns) so they can be sourced into either context.
|
|
34
|
+
#
|
|
35
|
+
# Composer classification is NOT owned here: every shape, glyph, border
|
|
36
|
+
# family, geometry rule, and verdict decision lives in the shared
|
|
37
|
+
# bin/fm-composer-lib.sh (fm_composer_classify_screen), sourced below and
|
|
38
|
+
# reused by every backend adapter so the decision cannot drift. This file
|
|
39
|
+
# keeps only tmux's genuine capture-side primitives - the styled pane
|
|
40
|
+
# capture, the #{cursor_y} cursor read, the pi foreground-process identity
|
|
41
|
+
# probe, and the capability descriptor - plus the busy detection and submit
|
|
42
|
+
# cores that consume the shared verdict.
|
|
43
|
+
|
|
44
|
+
# shellcheck source=bin/fm-composer-lib.sh
|
|
45
|
+
. "$(dirname -- "${BASH_SOURCE[0]}")/fm-composer-lib.sh"
|
|
46
|
+
# shellcheck source=bin/fm-cursor-lib.sh
|
|
47
|
+
. "$(dirname -- "${BASH_SOURCE[0]}")/fm-cursor-lib.sh"
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
# fm_tmux_strip_ghost: thin adapter over the shared, fleet-wide ghost extractor
|
|
51
|
+
# fm_composer_strip_ghost (bin/fm-composer-lib.sh). It drops de-emphasised
|
|
52
|
+
# ghost/placeholder runs - dim/faint (SGR 2, claude's/codex's/cursor's ghost) AND a
|
|
53
|
+
# dark/muted truecolor foreground (grok's placeholder) - from one captured,
|
|
54
|
+
# styled composer line and prints the plain, real-typed text. Kept as a named
|
|
55
|
+
# tmux entry point (and for existing callers/tests) but owns no logic of its own,
|
|
56
|
+
# so the tmux and herdr adapters cannot drift apart on what counts as ghost text.
|
|
57
|
+
fm_tmux_strip_ghost() { fm_composer_strip_ghost; }
|
|
58
|
+
|
|
59
|
+
# --- tmux composer capture and capability primitives ------------------------
|
|
60
|
+
#
|
|
61
|
+
# These four functions are the ONLY tmux-specific composer knowledge left:
|
|
62
|
+
# how to capture a styled screen, how to read the cursor row, how to probe a
|
|
63
|
+
# live pi agent, and the static capability facts. Every shape, glyph, border
|
|
64
|
+
# family, and verdict decision lives in the shared owner
|
|
65
|
+
# (bin/fm-composer-lib.sh, fm_composer_classify_screen), so a new harness
|
|
66
|
+
# shape is taught there once and never here.
|
|
67
|
+
|
|
68
|
+
# fm_tmux_composer_capture: the visible pane WITH ANSI styling. The styled
|
|
69
|
+
# capture is consumed internally by the classifier and is NEVER surfaced
|
|
70
|
+
# (fm-peek and every human/LLM-facing path stay plain).
|
|
71
|
+
fm_tmux_composer_capture() { # <target>
|
|
72
|
+
tmux capture-pane -e -p -t "$1" -S 0 -E - 2>/dev/null
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
# fm_tmux_composer_cursor_row: the pane's cursor row, zero-based, relative to
|
|
76
|
+
# the visible pane - tmux's genuine primitive that no other backend has.
|
|
77
|
+
fm_tmux_composer_cursor_row() { # <target>
|
|
78
|
+
tmux display-message -p -t "$1" '#{cursor_y}' 2>/dev/null
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
# fm_tmux_composer_caps: the tmux capability descriptor - static data, not
|
|
82
|
+
# logic (see the capability model in bin/fm-composer-lib.sh).
|
|
83
|
+
fm_tmux_composer_caps() {
|
|
84
|
+
printf 'styled=1\ncursor=1\nidentity=1\nrows=0\n'
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
# fm_tmux_composer_identity: the tmux agent-identity probe backing the
|
|
88
|
+
# separated (pi) composer shape, tmux's analogue of herdr's native
|
|
89
|
+
# `agent get`. It answers only for pi, from two live signals:
|
|
90
|
+
# - identity: the pane tty's FOREGROUND process group (pgid = tpgid, the
|
|
91
|
+
# same scoping as fm_backend_tmux_foreground_comms) contains a pi-family
|
|
92
|
+
# process (pi, pi-signed, pi-launcher - docs/verification/
|
|
93
|
+
# runtime-backends.md "Agent liveness name sources"), falling back to
|
|
94
|
+
# tmux's own foreground-derived #{pane_current_command}. A pane whose
|
|
95
|
+
# agent died to a shell has no pi foreground process and gets NO identity,
|
|
96
|
+
# which is exactly what keeps the strict blank-row rule honest: a blank
|
|
97
|
+
# row between two stale rules stays unknown.
|
|
98
|
+
# - status: pi's verified busy footer via fm_pane_is_busy, mapped onto the
|
|
99
|
+
# idle/working vocabulary herdr's probe reports natively.
|
|
100
|
+
# Prints "pi<TAB>idle" or "pi<TAB>working"; exits 1 when the pane is not a
|
|
101
|
+
# live pi.
|
|
102
|
+
fm_tmux_composer_identity() { # <target>
|
|
103
|
+
local target=$1 tty pgid tpgid comm found=0 status
|
|
104
|
+
tty=$(tmux display-message -p -t "$target" '#{pane_tty}' 2>/dev/null) || tty=
|
|
105
|
+
case "$tty" in
|
|
106
|
+
/dev/*)
|
|
107
|
+
while read -r _ pgid tpgid comm; do
|
|
108
|
+
[ -n "$comm" ] || continue
|
|
109
|
+
[ "$pgid" = "$tpgid" ] || continue
|
|
110
|
+
case "${comm##*/}" in
|
|
111
|
+
pi|pi-signed|pi-launcher|Pi) found=1 ;;
|
|
112
|
+
esac
|
|
113
|
+
done <<EOF
|
|
114
|
+
$(LC_ALL=C ps -t "${tty#/dev/}" -o pid=,pgid=,tpgid=,comm= 2>/dev/null)
|
|
115
|
+
EOF
|
|
116
|
+
;;
|
|
117
|
+
esac
|
|
118
|
+
if [ "$found" -ne 1 ]; then
|
|
119
|
+
comm=$(tmux display-message -p -t "$target" '#{pane_current_command}' 2>/dev/null) || comm=
|
|
120
|
+
case "${comm##*/}" in
|
|
121
|
+
pi|pi-signed|pi-launcher) found=1 ;;
|
|
122
|
+
esac
|
|
123
|
+
fi
|
|
124
|
+
[ "$found" -eq 1 ] || return 1
|
|
125
|
+
status=$(fm_pane_busy_state "$target" pi)
|
|
126
|
+
case "$status" in
|
|
127
|
+
busy) printf 'pi\tworking' ;;
|
|
128
|
+
idle) printf 'pi\tidle' ;;
|
|
129
|
+
*) return 1 ;;
|
|
130
|
+
esac
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
# fm_tmux_composer_state: the tmux composer verdict - a thin adapter over the
|
|
134
|
+
# shared screen classifier. The verdict contract (empty | pending |
|
|
135
|
+
# pending-unproven | unknown, positive proof required for empty, unrecognized
|
|
136
|
+
# future verdicts failing safe) is owned by bin/fm-composer-lib.sh. Identity
|
|
137
|
+
# is fetched lazily, only when the classifier reports the verdict depends on
|
|
138
|
+
# it (a pi separator pair under the cursor), so the common read never pays
|
|
139
|
+
# for the process probe.
|
|
140
|
+
fm_tmux_composer_state() { # <target> -> empty|pending|pending-unproven|unknown
|
|
141
|
+
local target=$1 cy pane verdict identity
|
|
142
|
+
cy=$(fm_tmux_composer_cursor_row "$target") || { printf 'unknown'; return 0; }
|
|
143
|
+
case "$cy" in ''|*[!0-9]*) printf 'unknown'; return 0 ;; esac
|
|
144
|
+
pane=$(fm_tmux_composer_capture "$target") || { printf 'unknown'; return 0; }
|
|
145
|
+
verdict=$(fm_composer_classify_screen "$(fm_tmux_composer_caps)" "$pane" "$cy")
|
|
146
|
+
if [ "$verdict" = need-identity ]; then
|
|
147
|
+
if ! identity=$(fm_tmux_composer_identity "$target") || [ -z "$identity" ]; then
|
|
148
|
+
identity=probe-absent
|
|
149
|
+
fi
|
|
150
|
+
verdict=$(fm_composer_classify_screen "$(fm_tmux_composer_caps)" "$pane" "$cy" "$identity")
|
|
151
|
+
[ "$verdict" != need-identity ] || verdict=unknown
|
|
152
|
+
fi
|
|
153
|
+
# Cursor Agent CLI parks its terminal cursor OUTSIDE its composer, below the
|
|
154
|
+
# footer, with #{cursor_flag} 0 - so on a Cursor pane tmux's cursor row is not
|
|
155
|
+
# a composer locator and the cursor-anchored read can only ever answer
|
|
156
|
+
# `unknown`. Reclassify that pane the way every cursorless backend already
|
|
157
|
+
# classifies it, letting the bottom-most shape win, which is the same rule
|
|
158
|
+
# herdr, zellij, cmux, and orca use for every harness including this one.
|
|
159
|
+
# Gated on Cursor's own structural process identity, never on the verdict
|
|
160
|
+
# alone, so the strict blank-row posture that owns `unknown` for every other
|
|
161
|
+
# harness is untouched.
|
|
162
|
+
if [ "$verdict" = unknown ] && fm_tmux_pane_is_cursor "$target"; then
|
|
163
|
+
verdict=$(fm_composer_classify_screen "$(fm_tmux_composer_caps)" "$pane" '')
|
|
164
|
+
fi
|
|
165
|
+
printf '%s' "$verdict"
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
# fm_tmux_pane_is_cursor: true when the pane's FOREGROUND process group contains
|
|
169
|
+
# a genuine Cursor Agent CLI process. Cursor runs as a bundled node script, so
|
|
170
|
+
# tmux's own #{pane_current_command} reports a bare `node`; identity therefore
|
|
171
|
+
# comes from Cursor's name or install tree in the command path or argv[0], whose
|
|
172
|
+
# single owner is bin/fm-cursor-lib.sh. The foreground scoping (pgid = tpgid)
|
|
173
|
+
# matches fm_tmux_composer_identity, so a pane whose agent exited to a shell has
|
|
174
|
+
# no Cursor foreground process and gets no reclassification.
|
|
175
|
+
fm_tmux_pane_is_cursor() { # <target>
|
|
176
|
+
local target=$1 tty pid pgid tpgid comm args argv0
|
|
177
|
+
tty=$(tmux display-message -p -t "$target" '#{pane_tty}' 2>/dev/null) || return 1
|
|
178
|
+
case "$tty" in /dev/*) ;; *) return 1 ;; esac
|
|
179
|
+
while read -r pid pgid tpgid comm; do
|
|
180
|
+
[ -n "$comm" ] || continue
|
|
181
|
+
[ "$pgid" = "$tpgid" ] || continue
|
|
182
|
+
args=$(LC_ALL=C ps -p "$pid" -o args= 2>/dev/null) || args=
|
|
183
|
+
args=${args#"${args%%[![:space:]]*}"}
|
|
184
|
+
argv0=${args%%[[:space:]]*}
|
|
185
|
+
fm_cursor_process_matches "$comm" '' "$argv0" && return 0
|
|
186
|
+
done <<EOF
|
|
187
|
+
$(LC_ALL=C ps -t "${tty#/dev/}" -o pid=,pgid=,tpgid=,comm= 2>/dev/null)
|
|
188
|
+
EOF
|
|
189
|
+
return 1
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
# fm_pane_input_pending: 0 when the composer is not proven empty, so pending
|
|
193
|
+
# text, ambiguous structure, unreadable state, and future verdicts all defer.
|
|
194
|
+
fm_pane_input_pending() { # <target>
|
|
195
|
+
[ "$(fm_tmux_composer_state "$1")" != empty ]
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
# fm_pane_is_busy: 0 if the pane's last few non-blank lines show a busy footer
|
|
199
|
+
# (an agent mid-turn). Scans a 40-line tail like fm-watch.sh.
|
|
200
|
+
fm_pane_busy_state() { # <target> [harness] -> busy|idle|unknown
|
|
201
|
+
local win=$1 harness=${2:-} tail40 visible
|
|
202
|
+
tail40=$(tmux capture-pane -p -t "$win" -S -40 2>/dev/null) \
|
|
203
|
+
|| { printf 'unknown'; return 0; }
|
|
204
|
+
visible=$(printf '%s' "$tail40" | grep -v '^[[:space:]]*$' | tail -12)
|
|
205
|
+
[ -n "$visible" ] || { printf 'unknown'; return 0; }
|
|
206
|
+
if printf '%s' "$visible" | fm_busy_lines_match "$harness"; then
|
|
207
|
+
printf 'busy'
|
|
208
|
+
else
|
|
209
|
+
printf 'idle'
|
|
210
|
+
fi
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
fm_pane_is_busy() { # <target> [harness]
|
|
214
|
+
[ "$(fm_pane_busy_state "$1" "${2:-}")" = busy ]
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
# fm_tmux_submit_core: type <text> into <target> ONCE, then submit with Enter,
|
|
218
|
+
# verifying the composer cleared. Retries Enter ONLY — never retypes, because a
|
|
219
|
+
# swallowed Enter leaves our text in the composer and retyping would duplicate
|
|
220
|
+
# it. Echoes the final proof-carrying verdict on stdout so callers can require
|
|
221
|
+
# exact `empty` before treating submission as confirmed.
|
|
222
|
+
# Busy-queued Enter (opencode 1.18.4): the harness accepts Enter while mid-turn
|
|
223
|
+
# and queues it for after the current turn, but keeps the typed text visible in
|
|
224
|
+
# the composer. Once the Enter-retry budget is spent and a structurally proven
|
|
225
|
+
# composer still reads "pending", the submit core falls back to
|
|
226
|
+
# `fm_pane_is_busy`: a busy pane means the Enter was accepted and queued (report
|
|
227
|
+
# `empty` so the caller does not re-send), while an idle pane keeps `pending` as
|
|
228
|
+
# a genuine swallow. Pending-unproven receives the same Enter retry budget but
|
|
229
|
+
# never reaches this exception.
|
|
230
|
+
# Turn-started confirmation (the strict blank-row posture's counterpart): a
|
|
231
|
+
# harness whose mid-turn screen the classifier cannot positively identify (pi
|
|
232
|
+
# replaces its separated composer while working) reads `unknown` right after a
|
|
233
|
+
# successful submit. When and only when the pane was IDLE before the text was
|
|
234
|
+
# typed, an idle-to-busy transition across our Enter is proof the harness
|
|
235
|
+
# accepted the submission - the same semantic signal herdr's native
|
|
236
|
+
# agent-state confirmation uses, read from the pane's verified busy footer.
|
|
237
|
+
# The busy read is polled across the remaining retry budget because the turn
|
|
238
|
+
# takes a beat to render. Without the baseline (a direct
|
|
239
|
+
# fm_tmux_submit_enter_core caller, or a pane already busy before typing) an
|
|
240
|
+
# `unknown` verdict is preserved untouched: busy conversion without the
|
|
241
|
+
# transition evidence could mark an undelivered message delivered.
|
|
242
|
+
fm_tmux_submit_enter_core() { # <target> <retries> <enter-sleep> [baseline-idle]
|
|
243
|
+
local target=$1 retries=$2 sleep_s=$3 baseline_idle=${4:-} i=0 j state busy_state
|
|
244
|
+
while :; do
|
|
245
|
+
tmux send-keys -t "$target" Enter 2>/dev/null || true
|
|
246
|
+
sleep "$sleep_s"
|
|
247
|
+
state=$(fm_tmux_composer_state "$target")
|
|
248
|
+
case "$state" in
|
|
249
|
+
pending|pending-unproven) ;;
|
|
250
|
+
unknown)
|
|
251
|
+
if [ "$baseline_idle" = 1 ]; then
|
|
252
|
+
j=0
|
|
253
|
+
while [ "$j" -lt "$retries" ]; do
|
|
254
|
+
if fm_pane_is_busy "$target"; then
|
|
255
|
+
printf 'empty'
|
|
256
|
+
return 0
|
|
257
|
+
fi
|
|
258
|
+
j=$((j + 1))
|
|
259
|
+
[ "$j" -ge "$retries" ] || sleep "$sleep_s"
|
|
260
|
+
done
|
|
261
|
+
fi
|
|
262
|
+
printf 'unknown'
|
|
263
|
+
return 0
|
|
264
|
+
;;
|
|
265
|
+
*) printf '%s' "$state"; return 0 ;;
|
|
266
|
+
esac
|
|
267
|
+
i=$((i + 1))
|
|
268
|
+
[ "$i" -lt "$retries" ] || break
|
|
269
|
+
done
|
|
270
|
+
if [ "$state" != pending ]; then
|
|
271
|
+
printf '%s' "$state"
|
|
272
|
+
return 0
|
|
273
|
+
fi
|
|
274
|
+
# Retries exhausted, composer still shows proven pending.
|
|
275
|
+
# Busy conversion is owned by fm_composer_queued_enter_verdict.
|
|
276
|
+
busy_state=idle
|
|
277
|
+
fm_pane_is_busy "$target" && busy_state=busy
|
|
278
|
+
fm_composer_queued_enter_verdict "$state" "$busy_state"
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
fm_tmux_submit_core() { # <target> <text> <retries> <enter-sleep> <settle>
|
|
282
|
+
local target=$1 text=$2 retries=$3 sleep_s=$4 settle=$5 baseline_idle='' baseline_state
|
|
283
|
+
# The turn-started baseline must predate our own typing: a pane already
|
|
284
|
+
# busy before the text lands can turn "busy" for reasons unrelated to our
|
|
285
|
+
# Enter, so only a clean idle-to-busy transition may confirm a submit.
|
|
286
|
+
baseline_state=$(fm_pane_busy_state "$target")
|
|
287
|
+
[ "$baseline_state" = idle ] && baseline_idle=1
|
|
288
|
+
tmux send-keys -t "$target" -l "$text" 2>/dev/null || { printf 'send-failed'; return 0; }
|
|
289
|
+
sleep "$settle"
|
|
290
|
+
fm_tmux_submit_enter_core "$target" "$retries" "$sleep_s" "$baseline_idle"
|
|
291
|
+
}
|