@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,716 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Ghost-text robustness (incident composer-robust; task afk-herdr-false-pending).
|
|
3
|
+
#
|
|
4
|
+
# A harness fills an otherwise-empty composer with de-emphasised ghost text that a
|
|
5
|
+
# plain pane capture cannot tell apart from human input, so the composer reader
|
|
6
|
+
# saw an idle pane as holding pending input. Two rendering styles are covered by
|
|
7
|
+
# the one shared ANSI-aware owner (fm_composer_strip_ghost, bin/fm-composer-lib.sh,
|
|
8
|
+
# reached here through the fm_tmux_strip_ghost thin adapter):
|
|
9
|
+
# - DIM/FAINT (SGR 2): claude's rotating prompt suggestion, codex's idle tip.
|
|
10
|
+
# - a dark/muted TRUECOLOR foreground: grok's placeholder/hint text.
|
|
11
|
+
# These tests pin:
|
|
12
|
+
# 1. fm_tmux_strip_ghost drops dim/faint AND dark-truecolor runs, keeping
|
|
13
|
+
# normal-intensity, brightly-coloured text.
|
|
14
|
+
# 2. fm_pane_input_pending reads a ghost-only composer (either style) as NOT
|
|
15
|
+
# pending, while still treating real (normal/bright) text as pending.
|
|
16
|
+
# 3. The tmux reader structurally scans every row of a multi-row composer.
|
|
17
|
+
# 4. The human/LLM-facing capture path (fm-peek.sh) stays PLAIN - no escape codes
|
|
18
|
+
# ever reach firstmate's context.
|
|
19
|
+
set -u
|
|
20
|
+
|
|
21
|
+
# shellcheck source=tests/lib.sh
|
|
22
|
+
. "$(dirname "${BASH_SOURCE[0]}")/lib.sh"
|
|
23
|
+
|
|
24
|
+
LIB="$ROOT/bin/fm-tmux-lib.sh"
|
|
25
|
+
PEEK="$ROOT/bin/fm-peek.sh"
|
|
26
|
+
|
|
27
|
+
# shellcheck source=/dev/null
|
|
28
|
+
. "$LIB"
|
|
29
|
+
|
|
30
|
+
TMP_ROOT=$(fm_test_tmproot fm-ghost-tests)
|
|
31
|
+
|
|
32
|
+
# ESC byte for building styled fixtures and asserting escape-free output.
|
|
33
|
+
ESC=$(printf '\033')
|
|
34
|
+
|
|
35
|
+
# A fake tmux that serves a styled composer line for the dim-aware reader and an
|
|
36
|
+
# escape-free line for the plain (peek) path. capture-pane returns the styled
|
|
37
|
+
# fixture verbatim WITH -e (mirrors `tmux capture-pane -e`), and the same content
|
|
38
|
+
# with SGR sequences stripped WITHOUT -e (mirrors a plain capture). cursor_y comes
|
|
39
|
+
# from FM_FAKE_CY. The fake deliberately returns the complete fixture for every
|
|
40
|
+
# capture, which exercises the structural scan while preserving the historical
|
|
41
|
+
# single-row fallback fixtures.
|
|
42
|
+
make_fake_tmux() { # <dir>
|
|
43
|
+
local dir=$1 fb="$1/fakebin"
|
|
44
|
+
mkdir -p "$fb"
|
|
45
|
+
cat > "$fb/tmux" <<'SH'
|
|
46
|
+
#!/usr/bin/env bash
|
|
47
|
+
set -u
|
|
48
|
+
case "${1:-}" in
|
|
49
|
+
display-message)
|
|
50
|
+
for a in "$@"; do case "$a" in *cursor_y*) printf '%s\n' "${FM_FAKE_CY:-0}"; exit 0 ;; esac; done
|
|
51
|
+
printf 'fakepane\n'; exit 0 ;;
|
|
52
|
+
capture-pane)
|
|
53
|
+
has_e=0
|
|
54
|
+
start= end= prev=
|
|
55
|
+
for a in "$@"; do
|
|
56
|
+
[ "$a" = "-e" ] && has_e=1
|
|
57
|
+
case "$prev" in
|
|
58
|
+
-S) start=$a ;;
|
|
59
|
+
-E) end=$a ;;
|
|
60
|
+
esac
|
|
61
|
+
prev=$a
|
|
62
|
+
done
|
|
63
|
+
f="${FM_FAKE_STYLED:-/dev/null}"
|
|
64
|
+
if [ -n "${FM_FAKE_ROW:-}" ] \
|
|
65
|
+
&& [ "$start" = "${FM_FAKE_CY:-0}" ] \
|
|
66
|
+
&& [ "$end" = "${FM_FAKE_CY:-0}" ]; then
|
|
67
|
+
f=$FM_FAKE_ROW
|
|
68
|
+
fi
|
|
69
|
+
if [ "$has_e" = 1 ]; then
|
|
70
|
+
cat "$f" 2>/dev/null
|
|
71
|
+
else
|
|
72
|
+
# Plain capture: drop SGR sequences, as real `tmux capture-pane -p` does.
|
|
73
|
+
LC_ALL=C awk '{gsub(/\033\[[0-9;]*m/, ""); print}' "$f" 2>/dev/null
|
|
74
|
+
fi
|
|
75
|
+
exit 0 ;;
|
|
76
|
+
list-windows) exit 0 ;;
|
|
77
|
+
esac
|
|
78
|
+
exit 1
|
|
79
|
+
SH
|
|
80
|
+
chmod +x "$fb/tmux"
|
|
81
|
+
printf '%s\n' "$fb"
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
# --- fm_tmux_strip_ghost (pure) ---------------------------------------------
|
|
85
|
+
|
|
86
|
+
test_strip_ghost_drops_dim_keeps_normal() {
|
|
87
|
+
local out
|
|
88
|
+
# Dim run between ESC[2m and ESC[0m is dropped; the prompt glyph survives.
|
|
89
|
+
out=$(printf '\xe2\x9d\xaf \033[2mWhat is the largest country by area?\033[0m\n' | fm_tmux_strip_ghost)
|
|
90
|
+
[ "$out" = "$(printf '\xe2\x9d\xaf ')" ] || fail "dim run not dropped: '$out'"
|
|
91
|
+
# Normal-intensity text is kept verbatim (no styling at all).
|
|
92
|
+
out=$(printf '\xe2\x9d\xaf real human text\n' | fm_tmux_strip_ghost)
|
|
93
|
+
[ "$out" = "$(printf '\xe2\x9d\xaf real human text')" ] || fail "normal text changed: '$out'"
|
|
94
|
+
# Bold (SGR 1) is normal-intensity, NOT dim - must be kept.
|
|
95
|
+
out=$(printf '\033[1mbold typed\033[0m\n' | fm_tmux_strip_ghost)
|
|
96
|
+
[ "$out" = "bold typed" ] || fail "bold text wrongly dropped: '$out'"
|
|
97
|
+
pass "fm_tmux_strip_ghost drops dim/faint runs, keeps normal and bold text"
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
test_strip_ghost_handles_combined_and_boundary_codes() {
|
|
101
|
+
local out
|
|
102
|
+
# Dim combined with a color in one sequence (ESC[2;37m) is still a dim run.
|
|
103
|
+
out=$(printf '\xe2\x9d\xaf \033[2;37mpredicted\033[0m\n' | fm_tmux_strip_ghost)
|
|
104
|
+
[ "$out" = "$(printf '\xe2\x9d\xaf ')" ] || fail "combined dim+color not dropped: '$out'"
|
|
105
|
+
# ESC[22m (normal intensity) ends a dim run mid-line; the tail is kept.
|
|
106
|
+
out=$(printf '\033[2mghost\033[22mREALTAIL\n' | fm_tmux_strip_ghost)
|
|
107
|
+
[ "$out" = "REALTAIL" ] || fail "ESC[22m did not end the dim run: '$out'"
|
|
108
|
+
# ESC[0;2m (reset then dim) reads as dim (left-to-right within the sequence).
|
|
109
|
+
out=$(printf 'keep\033[0;2mdrop\033[0m\n' | fm_tmux_strip_ghost)
|
|
110
|
+
[ "$out" = "keep" ] || fail "reset-then-dim not treated as dim: '$out'"
|
|
111
|
+
pass "fm_tmux_strip_ghost handles combined SGR, ESC[22m, and reset-then-dim"
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
test_strip_ghost_keeps_colored_text_with_2_payloads() {
|
|
115
|
+
local out
|
|
116
|
+
# These pin that the awk's truecolor/256-color `2` payload SELECTOR is not
|
|
117
|
+
# mistaken for the SGR-2 dim attribute. The truecolor foregrounds use a BRIGHT
|
|
118
|
+
# colour (grok's real-input RGB 224,222,244, luminance ~225), because a DARK
|
|
119
|
+
# truecolor foreground is now itself a ghost signal (grok's placeholder) and is
|
|
120
|
+
# covered by test_strip_ghost_drops_dark_truecolor_ghost below.
|
|
121
|
+
out=$(printf '\033[38;5;2mgreen typed\033[0m\n' | fm_tmux_strip_ghost)
|
|
122
|
+
[ "$out" = "green typed" ] || fail "8-bit color payload 2 was treated as dim: '$out'"
|
|
123
|
+
out=$(printf '\033[38;2;224;222;244mtruecolor typed\033[0m\n' | fm_tmux_strip_ghost)
|
|
124
|
+
[ "$out" = "truecolor typed" ] || fail "bright truecolor payload 2 was treated as dim/ghost: '$out'"
|
|
125
|
+
out=$(printf '\033[48;2;4;5;6mbackground typed\033[0m\n' | fm_tmux_strip_ghost)
|
|
126
|
+
[ "$out" = "background typed" ] || fail "background truecolor payload was treated as dim: '$out'"
|
|
127
|
+
out=$(printf '\033[58;5;2munderline-color typed\033[0m\n' | fm_tmux_strip_ghost)
|
|
128
|
+
[ "$out" = "underline-color typed" ] || fail "underline color payload 2 was treated as dim: '$out'"
|
|
129
|
+
out=$(printf '\033[38:2::224:222:244mcolon truecolor typed\033[0m\n' | fm_tmux_strip_ghost)
|
|
130
|
+
[ "$out" = "colon truecolor typed" ] || fail "bright colon truecolor payload 2 was treated as dim/ghost: '$out'"
|
|
131
|
+
out=$(printf '\033[58::5::2mcolon underline typed\033[0m\n' | fm_tmux_strip_ghost)
|
|
132
|
+
[ "$out" = "colon underline typed" ] || fail "colon underline SGR leaked or dimmed text: '$out'"
|
|
133
|
+
out=$(printf '\033[4:2mnot dim underline\033[0m\n' | fm_tmux_strip_ghost)
|
|
134
|
+
[ "$out" = "not dim underline" ] || fail "colon subparameter 2 was treated as dim: '$out'"
|
|
135
|
+
pass "fm_tmux_strip_ghost keeps bright colored text with 2 payloads"
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
# --- Dark truecolor foreground is ghost (grok placeholder), dropped ----------
|
|
139
|
+
|
|
140
|
+
test_strip_ghost_drops_dark_truecolor_ghost() {
|
|
141
|
+
local out
|
|
142
|
+
# grok renders its placeholder/hint text with a dark, muted truecolor
|
|
143
|
+
# foreground (empirically 38;2;50;47;70 .. 38;2;110;106;134, luminance ~51..110,
|
|
144
|
+
# verified live against grok 0.2.93; the pristine "Type a message..." placeholder
|
|
145
|
+
# was this shape in grok 0.2.82). The shared owner drops it while keeping the
|
|
146
|
+
# bright prompt glyph, so an idle grok composer never reads as pending.
|
|
147
|
+
out=$(printf '\xe2\x9d\xaf \033[38;2;50;47;70mType a message...\033[0m\n' | fm_tmux_strip_ghost)
|
|
148
|
+
[ "$out" = "$(printf '\xe2\x9d\xaf ')" ] || fail "dark truecolor ghost not dropped: '$out'"
|
|
149
|
+
out=$(printf '\033[38;2;110;106;134mplaceholder hint text\033[39m\n' | fm_tmux_strip_ghost)
|
|
150
|
+
[ -z "$out" ] || fail "dark truecolor hint not dropped: '$out'"
|
|
151
|
+
# The colon form drops too.
|
|
152
|
+
out=$(printf '\xe2\x9d\xaf \033[38:2::86:82:110mmuted\033[0m\n' | fm_tmux_strip_ghost)
|
|
153
|
+
[ "$out" = "$(printf '\xe2\x9d\xaf ')" ] || fail "dark colon-truecolor ghost not dropped: '$out'"
|
|
154
|
+
pass "fm_tmux_strip_ghost drops a dark/muted truecolor foreground (grok placeholder)"
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
# --- muse's composer sits closest to the ghost threshold ---------------------
|
|
158
|
+
|
|
159
|
+
# These are muse 0.1.0-R708.1's real captured composer rows. Its prompt glyph
|
|
160
|
+
# `⟩` is truecolor 38;2;90;160;255 (luminance ~149.9) and its typed text is
|
|
161
|
+
# 38;2;204;211;219 (~209.8), so the glyph clears the 128 default by the
|
|
162
|
+
# narrowest margin in the fleet - roughly a fifth of grok's real-input margin.
|
|
163
|
+
# Both must survive stripping: dropping the glyph would empty an idle composer's
|
|
164
|
+
# plain row, and dropping the typed text would read a pending pane as empty and
|
|
165
|
+
# make it an injection target.
|
|
166
|
+
test_strip_ghost_keeps_muse_composer_colors() {
|
|
167
|
+
local out glyph
|
|
168
|
+
glyph=$(printf '\xe2\x9f\xa9')
|
|
169
|
+
out=$(printf '\033[0m\033[38;2;90;160;255m\xe2\x9f\xa9 \033[39m\n' | fm_tmux_strip_ghost)
|
|
170
|
+
[ "$out" = "$(printf '%s ' "$glyph")" ] \
|
|
171
|
+
|| fail "muse's idle composer glyph was stripped as ghost text: '$out'"
|
|
172
|
+
# The submitted-prompt row carries a background colour too; an SGR 48 payload
|
|
173
|
+
# must not be luminance-tested as if it were the foreground.
|
|
174
|
+
out=$(printf '\033[38;2;90;160;255m\033[48;2;38;56;84m\xe2\x9f\xa9 \033[38;2;204;211;219mhello from firstmate\033[39m\n' | fm_tmux_strip_ghost)
|
|
175
|
+
[ "$out" = "$(printf '%s hello from firstmate' "$glyph")" ] \
|
|
176
|
+
|| fail "muse's typed text or background-coloured glyph row was stripped: '$out'"
|
|
177
|
+
# The restored prompt muse puts back into the composer after an Escape
|
|
178
|
+
# interrupt is real bright text and must stay visible as pending input.
|
|
179
|
+
out=$(printf '\033[0m\033[38;2;90;160;255m\xe2\x9f\xa9 \033[38;2;204;211;219msecond turn to interrupt\033[39m\n' | fm_tmux_strip_ghost)
|
|
180
|
+
[ "$out" = "$(printf '%s second turn to interrupt' "$glyph")" ] \
|
|
181
|
+
|| fail "muse's restored post-interrupt prompt was stripped as ghost text: '$out'"
|
|
182
|
+
pass "fm_tmux_strip_ghost keeps muse's near-threshold glyph and its typed text"
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
# --- fm_pane_input_pending: dim ghost is not pending ------------------------
|
|
186
|
+
|
|
187
|
+
test_dim_ghost_only_composer_is_not_pending() {
|
|
188
|
+
local dir fb capture
|
|
189
|
+
dir="$TMP_ROOT/ghost-only"; mkdir -p "$dir"
|
|
190
|
+
fb=$(make_fake_tmux "$dir")
|
|
191
|
+
capture="$dir/styled.txt"
|
|
192
|
+
# The exact rendering claude emits: a normal prompt glyph + a DIM predicted prompt.
|
|
193
|
+
printf '\xe2\x9d\xaf \033[2mWhat is the largest country by area?\033[0m\n' > "$capture"
|
|
194
|
+
if PATH="$fb:$PATH" FM_FAKE_STYLED="$capture" FM_FAKE_CY=0 \
|
|
195
|
+
fm_pane_input_pending "fakepane"; then
|
|
196
|
+
fail "dim ghost-only composer falsely read as pending"
|
|
197
|
+
fi
|
|
198
|
+
pass "fm_pane_input_pending: a dim ghost-only composer is NOT pending"
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
test_dim_ghost_inside_bordered_composer_is_not_pending() {
|
|
202
|
+
local dir fb capture
|
|
203
|
+
dir="$TMP_ROOT/ghost-bordered"; mkdir -p "$dir"
|
|
204
|
+
fb=$(make_fake_tmux "$dir")
|
|
205
|
+
capture="$dir/styled.txt"
|
|
206
|
+
# Bordered composer (claude box) holding only dim ghost text.
|
|
207
|
+
printf '╭─────────────────────────────────────╮\n│ \033[2mtry the other approach instead\033[0m │\n╰─────────────────────────────────────╯\n' > "$capture"
|
|
208
|
+
if PATH="$fb:$PATH" FM_FAKE_STYLED="$capture" FM_FAKE_CY=1 \
|
|
209
|
+
fm_pane_input_pending "fakepane"; then
|
|
210
|
+
fail "dim ghost in a bordered composer falsely read as pending"
|
|
211
|
+
fi
|
|
212
|
+
pass "fm_pane_input_pending: dim ghost inside a bordered composer is NOT pending"
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
test_normal_text_still_pending() {
|
|
216
|
+
local dir fb capture
|
|
217
|
+
dir="$TMP_ROOT/real-text"; mkdir -p "$dir"
|
|
218
|
+
fb=$(make_fake_tmux "$dir")
|
|
219
|
+
capture="$dir/styled.txt"
|
|
220
|
+
# Real human text, normal intensity - must still read as pending.
|
|
221
|
+
printf '\xe2\x9d\xaf fix findings 1 and 3, skip 2\n' > "$capture"
|
|
222
|
+
PATH="$fb:$PATH" FM_FAKE_STYLED="$capture" FM_FAKE_CY=0 \
|
|
223
|
+
fm_pane_input_pending "fakepane" \
|
|
224
|
+
|| fail "real typed text was not detected as pending"
|
|
225
|
+
pass "fm_pane_input_pending: normal-intensity typed text is still pending"
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
test_colored_text_with_2_payload_still_pending() {
|
|
229
|
+
local dir fb capture
|
|
230
|
+
dir="$TMP_ROOT/colored-text"; mkdir -p "$dir"
|
|
231
|
+
fb=$(make_fake_tmux "$dir")
|
|
232
|
+
capture="$dir/styled.txt"
|
|
233
|
+
printf '\xe2\x9d\xaf \033[38;5;2mgreen typed\033[0m\n' > "$capture"
|
|
234
|
+
PATH="$fb:$PATH" FM_FAKE_STYLED="$capture" FM_FAKE_CY=0 \
|
|
235
|
+
fm_pane_input_pending "fakepane" \
|
|
236
|
+
|| fail "8-bit colored typed text was not detected as pending"
|
|
237
|
+
printf '\xe2\x9d\xaf \033[38;2;224;222;244mtruecolor typed\033[0m\n' > "$capture"
|
|
238
|
+
PATH="$fb:$PATH" FM_FAKE_STYLED="$capture" FM_FAKE_CY=0 \
|
|
239
|
+
fm_pane_input_pending "fakepane" \
|
|
240
|
+
|| fail "bright truecolor typed text was not detected as pending"
|
|
241
|
+
printf '\xe2\x9d\xaf \033[58;5;2munderline-color typed\033[0m\n' > "$capture"
|
|
242
|
+
PATH="$fb:$PATH" FM_FAKE_STYLED="$capture" FM_FAKE_CY=0 \
|
|
243
|
+
fm_pane_input_pending "fakepane" \
|
|
244
|
+
|| fail "underline-colored typed text was not detected as pending"
|
|
245
|
+
printf '\xe2\x9d\xaf \033[58::5::2mcolon underline typed\033[0m\n' > "$capture"
|
|
246
|
+
PATH="$fb:$PATH" FM_FAKE_STYLED="$capture" FM_FAKE_CY=0 \
|
|
247
|
+
fm_pane_input_pending "fakepane" \
|
|
248
|
+
|| fail "colon underline typed text was not detected as pending"
|
|
249
|
+
pass "fm_pane_input_pending: bright colored text with 2 payloads is still pending"
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
test_dark_truecolor_ghost_only_composer_is_not_pending() {
|
|
253
|
+
local dir fb capture
|
|
254
|
+
dir="$TMP_ROOT/grok-ghost"; mkdir -p "$dir"
|
|
255
|
+
fb=$(make_fake_tmux "$dir")
|
|
256
|
+
capture="$dir/styled.txt"
|
|
257
|
+
# A grok-style pristine composer: bright prompt glyph + a dark/muted truecolor
|
|
258
|
+
# placeholder. It must read NOT pending (the grok TRUECOLOR gap, now covered by
|
|
259
|
+
# the same ANSI-aware owner as claude's dim ghost).
|
|
260
|
+
printf '\xe2\x9d\xaf \033[38;2;50;47;70mType a message...\033[0m\n' > "$capture"
|
|
261
|
+
if PATH="$fb:$PATH" FM_FAKE_STYLED="$capture" FM_FAKE_CY=0 \
|
|
262
|
+
fm_pane_input_pending "fakepane"; then
|
|
263
|
+
fail "dark truecolor ghost-only composer falsely read as pending"
|
|
264
|
+
fi
|
|
265
|
+
pass "fm_pane_input_pending: a dark truecolor ghost-only composer (grok placeholder) is NOT pending"
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
test_dark_truecolor_bare_shell_prompt_is_unknown() {
|
|
269
|
+
local dir fb capture out prompt
|
|
270
|
+
dir="$TMP_ROOT/dark-shell-prompt"; mkdir -p "$dir"
|
|
271
|
+
fb=$(make_fake_tmux "$dir")
|
|
272
|
+
capture="$dir/styled.txt"
|
|
273
|
+
for prompt in '$' 'user@host $'; do
|
|
274
|
+
printf '\033[38;2;50;47;70m%s\033[0m\n' "$prompt" > "$capture"
|
|
275
|
+
out=$(PATH="$fb:$PATH" FM_FAKE_STYLED="$capture" FM_FAKE_CY=0 \
|
|
276
|
+
fm_tmux_composer_state "fakepane")
|
|
277
|
+
[ "$out" = unknown ] \
|
|
278
|
+
|| fail "dark truecolor bare shell prompt '$prompt' must read unknown, got '$out'"
|
|
279
|
+
done
|
|
280
|
+
pass "fm_tmux_composer_state: dark truecolor shell prompts read unknown"
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
test_real_text_with_trailing_ghost_is_pending() {
|
|
284
|
+
local dir fb capture
|
|
285
|
+
dir="$TMP_ROOT/mixed"; mkdir -p "$dir"
|
|
286
|
+
fb=$(make_fake_tmux "$dir")
|
|
287
|
+
capture="$dir/styled.txt"
|
|
288
|
+
# A human typed "deploy" and claude appended a dim ghost completion. The real
|
|
289
|
+
# text must win - the composer is pending.
|
|
290
|
+
printf '\xe2\x9d\xaf deploy\033[2m the staging environment now\033[0m\n' > "$capture"
|
|
291
|
+
PATH="$fb:$PATH" FM_FAKE_STYLED="$capture" FM_FAKE_CY=0 \
|
|
292
|
+
fm_pane_input_pending "fakepane" \
|
|
293
|
+
|| fail "real text with a trailing ghost completion was not detected as pending"
|
|
294
|
+
pass "fm_pane_input_pending: real text plus a trailing ghost run is still pending"
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
# --- fm_tmux_composer_state: structural multi-row box scan ------------------
|
|
298
|
+
|
|
299
|
+
test_two_row_composer_reads_text_above_empty_cursor_row() {
|
|
300
|
+
local dir fb capture out
|
|
301
|
+
dir="$TMP_ROOT/two-row"; mkdir -p "$dir"
|
|
302
|
+
fb=$(make_fake_tmux "$dir")
|
|
303
|
+
capture="$dir/styled.txt"
|
|
304
|
+
cat > "$capture" <<'EOF'
|
|
305
|
+
╭────────────────────────────────────────────────────╮
|
|
306
|
+
│ > Read the brief at /tmp/brief.md and follow it. │
|
|
307
|
+
│ │
|
|
308
|
+
╰────────────────────────────────────────────────────╯
|
|
309
|
+
EOF
|
|
310
|
+
out=$(PATH="$fb:$PATH" FM_FAKE_STYLED="$capture" FM_FAKE_CY=2 \
|
|
311
|
+
fm_tmux_composer_state "fakepane")
|
|
312
|
+
[ "$out" = pending ] \
|
|
313
|
+
|| fail "two-row composer text above the empty cursor row should be pending, got '$out'"
|
|
314
|
+
pass "fm_tmux_composer_state: text above an empty cursor row is pending"
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
test_wrapped_composer_reads_all_content_rows() {
|
|
318
|
+
local dir fb capture out
|
|
319
|
+
dir="$TMP_ROOT/wrapped"; mkdir -p "$dir"
|
|
320
|
+
fb=$(make_fake_tmux "$dir")
|
|
321
|
+
capture="$dir/styled.txt"
|
|
322
|
+
cat > "$capture" <<'EOF'
|
|
323
|
+
╭────────────────────────────────────────────╮
|
|
324
|
+
│ > This deliberately long instruction wraps │
|
|
325
|
+
│ across a second composer content row and │
|
|
326
|
+
│ across a third composer content row too. │
|
|
327
|
+
│ │
|
|
328
|
+
╰────────────────────────────────────────────╯
|
|
329
|
+
EOF
|
|
330
|
+
out=$(PATH="$fb:$PATH" FM_FAKE_STYLED="$capture" FM_FAKE_CY=4 \
|
|
331
|
+
fm_tmux_composer_state "fakepane")
|
|
332
|
+
[ "$out" = pending ] \
|
|
333
|
+
|| fail "a three-row wrapped composer should be pending, got '$out'"
|
|
334
|
+
pass "fm_tmux_composer_state: a message wrapped across three rows is pending"
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
test_proven_box_bottom_border_cursor_classifies_content() {
|
|
338
|
+
local dir fb capture out
|
|
339
|
+
dir="$TMP_ROOT/bottom-border-ghost"; mkdir -p "$dir"
|
|
340
|
+
fb=$(make_fake_tmux "$dir")
|
|
341
|
+
capture="$dir/styled.txt"
|
|
342
|
+
printf '╭────────────────────────╮\n│ ❯ \033[38;2;50;47;70mType a message...\033[0m │\n╰──────── Grok 4.5 ──────╯\n' > "$capture"
|
|
343
|
+
out=$(PATH="$fb:$PATH" FM_FAKE_STYLED="$capture" FM_FAKE_CY=2 \
|
|
344
|
+
fm_tmux_composer_state "fakepane")
|
|
345
|
+
[ "$out" = empty ] \
|
|
346
|
+
|| fail "a cursor on a proven titled box bottom must classify its content, got '$out'"
|
|
347
|
+
pass "fm_tmux_composer_state: a proven titled box tolerates a bottom-border cursor"
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
test_pi_identity_requires_readable_busy_state() (
|
|
351
|
+
local out
|
|
352
|
+
# Keep the mocks in this subshell so they cannot affect later tests. Defining
|
|
353
|
+
# functions directly inside a command substitution does not parse in Bash 3.2.
|
|
354
|
+
# shellcheck disable=SC2329 # Mock invoked indirectly by the sourced adapter.
|
|
355
|
+
tmux() {
|
|
356
|
+
local arg
|
|
357
|
+
for arg in "$@"; do
|
|
358
|
+
case "$arg" in
|
|
359
|
+
*pane_tty*) printf '\n'; return 0 ;;
|
|
360
|
+
*pane_current_command*) printf 'pi\n'; return 0 ;;
|
|
361
|
+
esac
|
|
362
|
+
done
|
|
363
|
+
return 1
|
|
364
|
+
}
|
|
365
|
+
# shellcheck disable=SC2329 # Mock invoked indirectly by the sourced adapter.
|
|
366
|
+
fm_pane_busy_state() { printf 'unknown'; }
|
|
367
|
+
if out=$(fm_tmux_composer_identity fakepane); then
|
|
368
|
+
fail "a live Pi process with unreadable busy state must not produce identity, got '$out'"
|
|
369
|
+
fi
|
|
370
|
+
pass "fm_tmux_composer_identity: unknown busy state cannot become idle identity"
|
|
371
|
+
)
|
|
372
|
+
|
|
373
|
+
test_bordered_busy_signatures_are_pending() {
|
|
374
|
+
local dir fb capture out signature
|
|
375
|
+
dir="$TMP_ROOT/bordered-busy-signatures"; mkdir -p "$dir"
|
|
376
|
+
fb=$(make_fake_tmux "$dir")
|
|
377
|
+
capture="$dir/styled.txt"
|
|
378
|
+
for signature in 'Working...' 'Ctrl+c:cancel'; do
|
|
379
|
+
printf '╭────────────────────╮\n│ %-18s │\n╰────────────────────╯\n' "$signature" > "$capture"
|
|
380
|
+
out=$(PATH="$fb:$PATH" FM_FAKE_STYLED="$capture" FM_FAKE_CY=1 \
|
|
381
|
+
fm_tmux_composer_state "fakepane")
|
|
382
|
+
[ "$out" = pending ] \
|
|
383
|
+
|| fail "typed bordered busy signature '$signature' should be pending, got '$out'"
|
|
384
|
+
done
|
|
385
|
+
pass "fm_tmux_composer_state: typed Pi and Grok busy signatures inside a box are pending"
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
test_non_bordered_busy_footer_is_unknown_strict() {
|
|
389
|
+
# STRICT divergence (captain decision blank-row-injection-posture): a bare
|
|
390
|
+
# busy-footer row under the cursor is not a composer container, so it no
|
|
391
|
+
# longer reads `empty` the way the old allow-busy compatibility fallback
|
|
392
|
+
# did. Its one load-bearing consumer - submit confirmation on a harness
|
|
393
|
+
# whose mid-turn screen hides the composer (pi) - moved to the submit
|
|
394
|
+
# core's baseline-idle turn-started conversion (fm_tmux_submit_core), which
|
|
395
|
+
# requires an idle-to-busy transition across our own Enter instead of
|
|
396
|
+
# trusting any busy-looking row.
|
|
397
|
+
local dir fb capture out
|
|
398
|
+
dir="$TMP_ROOT/non-bordered-busy"; mkdir -p "$dir"
|
|
399
|
+
fb=$(make_fake_tmux "$dir")
|
|
400
|
+
capture="$dir/styled.txt"
|
|
401
|
+
printf 'Working...\n' > "$capture"
|
|
402
|
+
out=$(PATH="$fb:$PATH" FM_FAKE_STYLED="$capture" FM_FAKE_CY=0 \
|
|
403
|
+
fm_tmux_composer_state "fakepane")
|
|
404
|
+
[ "$out" = unknown ] \
|
|
405
|
+
|| fail "a non-bordered busy footer must read unknown under the strict rule, got '$out'"
|
|
406
|
+
pass "fm_tmux_composer_state: a bare busy-footer row reads unknown (strict container-proof rule)"
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
test_clipped_bordered_box_is_unknown() {
|
|
410
|
+
local dir fb capture out
|
|
411
|
+
dir="$TMP_ROOT/clipped-box"; mkdir -p "$dir"
|
|
412
|
+
fb=$(make_fake_tmux "$dir")
|
|
413
|
+
capture="$dir/styled.txt"
|
|
414
|
+
printf '╭────────────────────╮\n│ > │\n' > "$capture"
|
|
415
|
+
out=$(PATH="$fb:$PATH" FM_FAKE_STYLED="$capture" FM_FAKE_CY=1 \
|
|
416
|
+
fm_tmux_composer_state "fakepane")
|
|
417
|
+
[ "$out" = unknown ] \
|
|
418
|
+
|| fail "a bordered box with no readable bottom border should be unknown, got '$out'"
|
|
419
|
+
pass "fm_tmux_composer_state: an unbounded bordered box fails closed as unknown"
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
test_asymmetric_composer_edges_are_unknown() {
|
|
423
|
+
local dir fb capture out row
|
|
424
|
+
dir="$TMP_ROOT/asymmetric-box"; mkdir -p "$dir"
|
|
425
|
+
fb=$(make_fake_tmux "$dir")
|
|
426
|
+
capture="$dir/styled.txt"
|
|
427
|
+
for row in '│ > text' 'text │' '│ > text ┃' '──────' '+----' 'text +'; do
|
|
428
|
+
printf '%s\n' "$row" > "$capture"
|
|
429
|
+
out=$(PATH="$fb:$PATH" LC_ALL=C FM_FAKE_STYLED="$capture" FM_FAKE_CY=0 \
|
|
430
|
+
fm_tmux_composer_state "fakepane")
|
|
431
|
+
[ "$out" = unknown ] \
|
|
432
|
+
|| fail "unbounded composer-edge row '$row' should be unknown, got '$out'"
|
|
433
|
+
done
|
|
434
|
+
pass "fm_tmux_composer_state: clipped and asymmetric composer edges fail closed"
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
test_mismatched_box_families_are_unknown() {
|
|
438
|
+
local dir fb capture out
|
|
439
|
+
dir="$TMP_ROOT/mismatched-box"; mkdir -p "$dir"
|
|
440
|
+
fb=$(make_fake_tmux "$dir")
|
|
441
|
+
capture="$dir/styled.txt"
|
|
442
|
+
printf '╭────────╮\n┃ > ┃\n╰────────╯\n' > "$capture"
|
|
443
|
+
out=$(PATH="$fb:$PATH" FM_FAKE_STYLED="$capture" FM_FAKE_CY=1 \
|
|
444
|
+
fm_tmux_composer_state "fakepane")
|
|
445
|
+
[ "$out" = unknown ] \
|
|
446
|
+
|| fail "a box with mismatched border families should be unknown, got '$out'"
|
|
447
|
+
pass "fm_tmux_composer_state: inconsistent box geometry fails closed"
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
test_misaligned_box_is_unknown() {
|
|
451
|
+
local dir fb capture out fixture
|
|
452
|
+
dir="$TMP_ROOT/misaligned-box"; mkdir -p "$dir"
|
|
453
|
+
fb=$(make_fake_tmux "$dir")
|
|
454
|
+
capture="$dir/styled.txt"
|
|
455
|
+
for fixture in offset width; do
|
|
456
|
+
case "$fixture" in
|
|
457
|
+
offset) printf ' ╭────╮\n │ │\n╰────╯\n' > "$capture" ;;
|
|
458
|
+
width) printf '╭────╮\n│ │\n╰────╯\n' > "$capture" ;;
|
|
459
|
+
esac
|
|
460
|
+
out=$(PATH="$fb:$PATH" FM_FAKE_STYLED="$capture" FM_FAKE_CY=1 \
|
|
461
|
+
fm_tmux_composer_state "fakepane")
|
|
462
|
+
[ "$out" = unknown ] \
|
|
463
|
+
|| fail "a box with inconsistent $fixture geometry should be unknown, got '$out'"
|
|
464
|
+
done
|
|
465
|
+
pass "fm_tmux_composer_state: misaligned box bounds fail closed"
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
test_unproved_empty_geometry_fails_closed() {
|
|
469
|
+
local dir fb capture out fixture expected
|
|
470
|
+
dir="$TMP_ROOT/unproved-empty-geometry"; mkdir -p "$dir"
|
|
471
|
+
fb=$(make_fake_tmux "$dir")
|
|
472
|
+
capture="$dir/styled.txt"
|
|
473
|
+
for fixture in ghost idle malformed-top; do
|
|
474
|
+
case "$fixture" in
|
|
475
|
+
ghost)
|
|
476
|
+
expected=unknown
|
|
477
|
+
printf '╭────────────╮\n│ \033[2mghost\033[0m │\n╰────────────╯\n' > "$capture"
|
|
478
|
+
out=$(PATH="$fb:$PATH" FM_FAKE_STYLED="$capture" FM_FAKE_CY=1 \
|
|
479
|
+
fm_tmux_composer_state "fakepane")
|
|
480
|
+
;;
|
|
481
|
+
idle)
|
|
482
|
+
expected=pending-unproven
|
|
483
|
+
printf '╭────────────╮\n│ idle hint │\n╰────────────╯\n' > "$capture"
|
|
484
|
+
out=$(PATH="$fb:$PATH" FM_FAKE_STYLED="$capture" FM_FAKE_CY=1 \
|
|
485
|
+
FM_COMPOSER_IDLE_RE='^idle hint$' fm_tmux_composer_state "fakepane")
|
|
486
|
+
;;
|
|
487
|
+
malformed-top)
|
|
488
|
+
expected=unknown
|
|
489
|
+
printf '╭────x───────╮\n│ │\n╰────────────╯\n' > "$capture"
|
|
490
|
+
out=$(PATH="$fb:$PATH" FM_FAKE_STYLED="$capture" FM_FAKE_CY=1 \
|
|
491
|
+
fm_tmux_composer_state "fakepane")
|
|
492
|
+
;;
|
|
493
|
+
esac
|
|
494
|
+
[ "$out" = "$expected" ] \
|
|
495
|
+
|| fail "unproved geometry '$fixture' should be $expected, got '$out'"
|
|
496
|
+
done
|
|
497
|
+
pass "fm_tmux_composer_state: unproved ghost and malformed geometry stay unknown while styled placeholder-like text stays pending-unproven"
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
test_differing_widths_use_asymmetric_verdicts() {
|
|
501
|
+
local dir fb capture out
|
|
502
|
+
dir="$TMP_ROOT/differing-widths"; mkdir -p "$dir"
|
|
503
|
+
fb=$(make_fake_tmux "$dir")
|
|
504
|
+
capture="$dir/styled.txt"
|
|
505
|
+
printf '╭──────────╮\n│ > text │\n╰──────────╯\n' > "$capture"
|
|
506
|
+
out=$(PATH="$fb:$PATH" FM_FAKE_STYLED="$capture" FM_FAKE_CY=1 \
|
|
507
|
+
fm_tmux_composer_state "fakepane")
|
|
508
|
+
[ "$out" = pending-unproven ] \
|
|
509
|
+
|| fail "text in a differing-width box should be pending-unproven, got '$out'"
|
|
510
|
+
printf '╭──────────╮\n│ │\n╰──────────╯\n' > "$capture"
|
|
511
|
+
out=$(PATH="$fb:$PATH" FM_FAKE_STYLED="$capture" FM_FAKE_CY=1 \
|
|
512
|
+
fm_tmux_composer_state "fakepane")
|
|
513
|
+
[ "$out" = unknown ] \
|
|
514
|
+
|| fail "an empty differing-width box should be unknown, never empty, got '$out'"
|
|
515
|
+
pass "fm_tmux_composer_state: differing widths prefer pending or unknown, never empty"
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
test_wide_composer_text_is_pending() {
|
|
519
|
+
local dir fb capture out text
|
|
520
|
+
dir="$TMP_ROOT/wide-text"; mkdir -p "$dir"
|
|
521
|
+
fb=$(make_fake_tmux "$dir")
|
|
522
|
+
capture="$dir/styled.txt"
|
|
523
|
+
for text in '修复登录问题' 'fix the bug 🔧'; do
|
|
524
|
+
printf '╭────────────────────╮\n│ > %s │\n╰────────────────────╯\n' "$text" > "$capture"
|
|
525
|
+
out=$(PATH="$fb:$PATH" LC_ALL=C FM_FAKE_STYLED="$capture" FM_FAKE_CY=1 \
|
|
526
|
+
fm_tmux_composer_state "fakepane")
|
|
527
|
+
[ "$out" = pending-unproven ] \
|
|
528
|
+
|| fail "wide composer text '$text' should be pending-unproven, got '$out'"
|
|
529
|
+
done
|
|
530
|
+
pass "fm_tmux_composer_state: emoji and CJK text remain pending under the C locale"
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
test_all_tmux_harness_composers_share_classification() {
|
|
534
|
+
local dir fb capture out harness
|
|
535
|
+
dir="$TMP_ROOT/all-harness-composers"; mkdir -p "$dir"
|
|
536
|
+
fb=$(make_fake_tmux "$dir")
|
|
537
|
+
capture="$dir/styled.txt"
|
|
538
|
+
for harness in claude codex opencode pi pi-signed grok; do
|
|
539
|
+
case "$harness" in
|
|
540
|
+
claude) printf '╭────────────╮\n│ ❯ \033[2mtry\033[0m │\n╰────────────╯\n' > "$capture" ;;
|
|
541
|
+
codex) printf '╭────────────╮\n│ › \033[2mtip\033[0m │\n╰────────────╯\n' > "$capture" ;;
|
|
542
|
+
opencode) printf '╭────────────╮\n│ > │\n╰────────────╯\n' > "$capture" ;;
|
|
543
|
+
pi|pi-signed) printf '╭────────────╮\n│ │\n╰────────────╯\n' > "$capture" ;;
|
|
544
|
+
grok) printf '╭────────────╮\n│ ❯ \033[38;2;50;47;70mType\033[0m │\n╰────────────╯\n' > "$capture" ;;
|
|
545
|
+
esac
|
|
546
|
+
out=$(PATH="$fb:$PATH" FM_FAKE_STYLED="$capture" FM_FAKE_CY=1 \
|
|
547
|
+
fm_tmux_composer_state "fakepane")
|
|
548
|
+
[ "$out" = empty ] \
|
|
549
|
+
|| fail "$harness aligned idle composer should be empty, got '$out'"
|
|
550
|
+
case "$harness" in
|
|
551
|
+
claude|grok) printf '╭────────────╮\n│ ❯ fix │\n╰────────────╯\n' > "$capture" ;;
|
|
552
|
+
codex) printf '╭────────────╮\n│ › fix │\n╰────────────╯\n' > "$capture" ;;
|
|
553
|
+
opencode|pi|pi-signed) printf '╭────────────╮\n│ > fix │\n╰────────────╯\n' > "$capture" ;;
|
|
554
|
+
esac
|
|
555
|
+
out=$(PATH="$fb:$PATH" FM_FAKE_STYLED="$capture" FM_FAKE_CY=1 \
|
|
556
|
+
fm_tmux_composer_state "fakepane")
|
|
557
|
+
[ "$out" = pending ] \
|
|
558
|
+
|| fail "$harness composer with text should be pending, got '$out'"
|
|
559
|
+
done
|
|
560
|
+
pass "fm_tmux_composer_state: all tmux harnesses share empty and pending classification"
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
test_unrecognized_state_defers_input_guard() {
|
|
564
|
+
(
|
|
565
|
+
# shellcheck disable=SC2329
|
|
566
|
+
fm_tmux_composer_state() { printf 'future-state'; }
|
|
567
|
+
fm_pane_input_pending "fakepane"
|
|
568
|
+
) || fail "an unrecognized composer state should defer the input guard"
|
|
569
|
+
pass "fm_pane_input_pending: unrecognized states defer by default"
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
test_single_capture_leaves_no_fallback_race() {
|
|
573
|
+
# The old reader captured twice (a full-pane scan, then a separate
|
|
574
|
+
# cursor-row band capture), so a pane redraw between the two could hand the
|
|
575
|
+
# verdict a row the scan never saw. The consolidated reader classifies ONE
|
|
576
|
+
# capture (bin/fm-composer-lib.sh, fm_composer_classify_screen), so the
|
|
577
|
+
# race is structurally gone: a divergent band-capture row (served via
|
|
578
|
+
# FM_FAKE_ROW, which only a band capture would read) must have no effect on
|
|
579
|
+
# the verdict.
|
|
580
|
+
local dir fb capture row_capture out
|
|
581
|
+
dir="$TMP_ROOT/fallback-race"; mkdir -p "$dir"
|
|
582
|
+
fb=$(make_fake_tmux "$dir")
|
|
583
|
+
capture="$dir/styled.txt"
|
|
584
|
+
row_capture="$dir/row.txt"
|
|
585
|
+
printf '› deploy staging\n' > "$capture"
|
|
586
|
+
printf '│ > │\n' > "$row_capture"
|
|
587
|
+
out=$(PATH="$fb:$PATH" FM_FAKE_STYLED="$capture" FM_FAKE_ROW="$row_capture" FM_FAKE_CY=0 \
|
|
588
|
+
fm_tmux_composer_state "fakepane")
|
|
589
|
+
[ "$out" = pending ] \
|
|
590
|
+
|| fail "the verdict must come from the one full capture (agent glyph + typed text = pending), got '$out'"
|
|
591
|
+
pass "fm_tmux_composer_state: one capture feeds the classifier; no band-capture race remains"
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
test_absent_tmux_identity_keeps_enclosed_bare_verdict() {
|
|
595
|
+
local dir fb capture out nbsp
|
|
596
|
+
dir="$TMP_ROOT/absent-identity"; mkdir -p "$dir"
|
|
597
|
+
fb=$(make_fake_tmux "$dir")
|
|
598
|
+
capture="$dir/styled.txt"
|
|
599
|
+
nbsp=$(printf '\302\240')
|
|
600
|
+
printf '────────────────────────\n❯%s\n────────────────────────\n' "$nbsp" > "$capture"
|
|
601
|
+
out=$(PATH="$fb:$PATH" FM_FAKE_STYLED="$capture" FM_FAKE_CY=1 \
|
|
602
|
+
fm_tmux_composer_state "fakepane")
|
|
603
|
+
[ "$out" = empty ] \
|
|
604
|
+
|| fail "an enclosed Claude glyph must keep its bare empty verdict when the Pi-only probe is absent, got '$out'"
|
|
605
|
+
pass "fm_tmux_composer_state: absent Pi identity preserves Claude's enclosed bare verdict"
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
test_legitimate_empty_routes_remain_empty() {
|
|
609
|
+
local dir fb capture out fixture cursor
|
|
610
|
+
dir="$TMP_ROOT/legitimate-empty"; mkdir -p "$dir"
|
|
611
|
+
fb=$(make_fake_tmux "$dir")
|
|
612
|
+
capture="$dir/styled.txt"
|
|
613
|
+
# A blank pane is deliberately absent here: under the strict container-proof
|
|
614
|
+
# rule (captain decision blank-row-injection-posture) a blank cursor row is
|
|
615
|
+
# unknown, pinned by tests/fm-daemon.test.sh and tests/fm-composer-lib.test.sh.
|
|
616
|
+
for fixture in bordered double-bordered agent-prompt; do
|
|
617
|
+
case "$fixture" in
|
|
618
|
+
bordered) printf '╭────╮\n│ │\n╰────╯\n' > "$capture"; cursor=1 ;;
|
|
619
|
+
double-bordered) printf '╔════╗\n║ ║\n╚════╝\n' > "$capture"; cursor=1 ;;
|
|
620
|
+
agent-prompt) printf '›\n' > "$capture"; cursor=0 ;;
|
|
621
|
+
esac
|
|
622
|
+
out=$(PATH="$fb:$PATH" FM_FAKE_STYLED="$capture" FM_FAKE_CY="$cursor" \
|
|
623
|
+
fm_tmux_composer_state "fakepane")
|
|
624
|
+
[ "$out" = empty ] \
|
|
625
|
+
|| fail "legitimate empty route '$fixture' should remain empty, got '$out'"
|
|
626
|
+
done
|
|
627
|
+
pass "fm_tmux_composer_state: only proven structural and non-bordered empty routes stay empty"
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
test_non_bordered_composer_uses_compatibility_fallback() {
|
|
631
|
+
local dir fb capture out
|
|
632
|
+
dir="$TMP_ROOT/non-bordered-fallback"; mkdir -p "$dir"
|
|
633
|
+
fb=$(make_fake_tmux "$dir")
|
|
634
|
+
capture="$dir/styled.txt"
|
|
635
|
+
printf '› deploy staging\n' > "$capture"
|
|
636
|
+
out=$(PATH="$fb:$PATH" FM_FAKE_STYLED="$capture" FM_FAKE_CY=0 \
|
|
637
|
+
fm_tmux_composer_state "fakepane")
|
|
638
|
+
[ "$out" = pending ] \
|
|
639
|
+
|| fail "a non-bordered composer should retain cursor-row classification, got '$out'"
|
|
640
|
+
pass "fm_tmux_composer_state: panes without bordered structure retain compatibility fallback"
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
test_non_bordered_interior_edges_are_pending() {
|
|
644
|
+
local dir fb capture out row
|
|
645
|
+
dir="$TMP_ROOT/non-bordered-interior-edges"; mkdir -p "$dir"
|
|
646
|
+
fb=$(make_fake_tmux "$dir")
|
|
647
|
+
capture="$dir/styled.txt"
|
|
648
|
+
for row in '› cat file | grep x' '› explain │ this glyph'; do
|
|
649
|
+
printf '%s\n' "$row" > "$capture"
|
|
650
|
+
out=$(PATH="$fb:$PATH" LC_ALL=C FM_FAKE_STYLED="$capture" FM_FAKE_CY=0 \
|
|
651
|
+
fm_tmux_composer_state "fakepane")
|
|
652
|
+
[ "$out" = pending ] \
|
|
653
|
+
|| fail "non-bordered interior edge row '$row' should be pending, got '$out'"
|
|
654
|
+
done
|
|
655
|
+
pass "fm_tmux_composer_state: interior edge glyphs retain non-bordered fallback"
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
# --- fm-peek.sh stays escape-free (LLM-facing path) -------------------------
|
|
659
|
+
|
|
660
|
+
test_peek_output_is_escape_free() {
|
|
661
|
+
local dir fb capture home out
|
|
662
|
+
dir="$TMP_ROOT/peek"; mkdir -p "$dir"
|
|
663
|
+
fb=$(make_fake_tmux "$dir")
|
|
664
|
+
capture="$dir/styled.txt"
|
|
665
|
+
# A pane full of styling, including dim ghost text. The plain peek path must
|
|
666
|
+
# surface NONE of these escape codes into firstmate's context.
|
|
667
|
+
printf 'normal output line\n\xe2\x9d\xaf \033[2mpredicted next prompt\033[0m\n' > "$capture"
|
|
668
|
+
# Empty FM_HOME so fm-guard.sh finds no in-flight task and stays silent.
|
|
669
|
+
home="$dir/home"; mkdir -p "$home/state"
|
|
670
|
+
# Pass an explicit session:window so resolution needs no metadata.
|
|
671
|
+
out=$(PATH="$fb:$PATH" FM_HOME="$home" FM_FAKE_STYLED="$capture" \
|
|
672
|
+
"$PEEK" "sess:win" 2>/dev/null)
|
|
673
|
+
case "$out" in
|
|
674
|
+
*"$ESC"*) fail "fm-peek surfaced ANSI escape codes into LLM-facing output" ;;
|
|
675
|
+
esac
|
|
676
|
+
# And it should still carry the real content.
|
|
677
|
+
case "$out" in
|
|
678
|
+
*"predicted next prompt"*) : ;;
|
|
679
|
+
*) fail "fm-peek dropped pane content (expected the ghost text body as plain text)" ;;
|
|
680
|
+
esac
|
|
681
|
+
pass "fm-peek output is escape-free (no raw -e bytes reach firstmate context)"
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
test_strip_ghost_drops_dim_keeps_normal
|
|
685
|
+
test_strip_ghost_handles_combined_and_boundary_codes
|
|
686
|
+
test_strip_ghost_keeps_colored_text_with_2_payloads
|
|
687
|
+
test_strip_ghost_drops_dark_truecolor_ghost
|
|
688
|
+
test_strip_ghost_keeps_muse_composer_colors
|
|
689
|
+
test_dim_ghost_only_composer_is_not_pending
|
|
690
|
+
test_dim_ghost_inside_bordered_composer_is_not_pending
|
|
691
|
+
test_normal_text_still_pending
|
|
692
|
+
test_colored_text_with_2_payload_still_pending
|
|
693
|
+
test_dark_truecolor_ghost_only_composer_is_not_pending
|
|
694
|
+
test_dark_truecolor_bare_shell_prompt_is_unknown
|
|
695
|
+
test_real_text_with_trailing_ghost_is_pending
|
|
696
|
+
test_two_row_composer_reads_text_above_empty_cursor_row
|
|
697
|
+
test_wrapped_composer_reads_all_content_rows
|
|
698
|
+
test_proven_box_bottom_border_cursor_classifies_content
|
|
699
|
+
test_pi_identity_requires_readable_busy_state
|
|
700
|
+
test_bordered_busy_signatures_are_pending
|
|
701
|
+
test_non_bordered_busy_footer_is_unknown_strict
|
|
702
|
+
test_clipped_bordered_box_is_unknown
|
|
703
|
+
test_asymmetric_composer_edges_are_unknown
|
|
704
|
+
test_mismatched_box_families_are_unknown
|
|
705
|
+
test_misaligned_box_is_unknown
|
|
706
|
+
test_unproved_empty_geometry_fails_closed
|
|
707
|
+
test_differing_widths_use_asymmetric_verdicts
|
|
708
|
+
test_wide_composer_text_is_pending
|
|
709
|
+
test_all_tmux_harness_composers_share_classification
|
|
710
|
+
test_unrecognized_state_defers_input_guard
|
|
711
|
+
test_single_capture_leaves_no_fallback_race
|
|
712
|
+
test_absent_tmux_identity_keeps_enclosed_bare_verdict
|
|
713
|
+
test_legitimate_empty_routes_remain_empty
|
|
714
|
+
test_non_bordered_composer_uses_compatibility_fallback
|
|
715
|
+
test_non_bordered_interior_edges_are_pending
|
|
716
|
+
test_peek_output_is_escape_free
|