@zerwiz/ymir 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/README.md +291 -0
- package/.agents/agents/bragi-marketer.md +111 -0
- package/.agents/agents/brokk.md +352 -0
- package/.agents/agents/forseti-reviewer.md +93 -0
- package/.agents/agents/frigg-consent.md +77 -0
- package/.agents/agents/groa-update.md +77 -0
- package/.agents/agents/hnoss-designer.md +69 -0
- package/.agents/agents/huginn-researcher.md +99 -0
- package/.agents/agents/jord-projects.md +78 -0
- package/.agents/agents/kvasir-scout.md +91 -0
- package/.agents/agents/mimir-planner.md +92 -0
- package/.agents/agents/muninn-stow.md +77 -0
- package/.agents/agents/saga-bearings.md +78 -0
- package/.agents/agents/sindri-developer.md +114 -0
- package/.agents/agents/snotra-documenter.md +105 -0
- package/.agents/agents/syn-recovery.md +78 -0
- package/.agents/agents/tyr-check.md +78 -0
- package/.agents/agents/urdh-hold.md +77 -0
- package/.agents/agents/volundr-smith.md +80 -0
- package/.agents/agents/vor-diagnostics.md +77 -0
- package/.agents/assets/agents/naming.md +50 -0
- package/.agents/assets/agents/registry.md +93 -0
- package/.agents/assets/agents/runtime.md +36 -0
- package/.agents/assets/agents/toon-tasks-cli.md +42 -0
- package/.agents/assets/templates/company_entity.template.md +37 -0
- package/.agents/backend/backends/cmux.sh +649 -0
- package/.agents/backend/backends/herdr-eventwait.py +157 -0
- package/.agents/backend/backends/herdr-workspace-move.py +114 -0
- package/.agents/backend/backends/herdr.sh +3386 -0
- package/.agents/backend/backends/orca.sh +290 -0
- package/.agents/backend/backends/tmux.sh +357 -0
- package/.agents/backend/backends/zellij.sh +700 -0
- package/.agents/backend/fm-afk-launch.sh +654 -0
- package/.agents/backend/fm-afk-return.sh +241 -0
- package/.agents/backend/fm-afk-start.sh +172 -0
- package/.agents/backend/fm-arm-command-policy.mjs +960 -0
- package/.agents/backend/fm-arm-pretool-check.sh +200 -0
- package/.agents/backend/fm-backend-hometag-lib.sh +52 -0
- package/.agents/backend/fm-backend.sh +981 -0
- package/.agents/backend/fm-backlog-handoff.sh +909 -0
- package/.agents/backend/fm-backlog-receive.sh +187 -0
- package/.agents/backend/fm-backlog-transition-lib.sh +779 -0
- package/.agents/backend/fm-bearings-board.sh +204 -0
- package/.agents/backend/fm-bearings-snapshot.sh +546 -0
- package/.agents/backend/fm-bootstrap.sh +1568 -0
- package/.agents/backend/fm-branch-outcome.sh +203 -0
- package/.agents/backend/fm-branch-prompt.sh +101 -0
- package/.agents/backend/fm-brief.sh +452 -0
- package/.agents/backend/fm-busy-event.sh +234 -0
- package/.agents/backend/fm-busy-lib.sh +986 -0
- package/.agents/backend/fm-captain-hold.sh +1001 -0
- package/.agents/backend/fm-cd-command-policy.mjs +153 -0
- package/.agents/backend/fm-cd-pretool-check.sh +190 -0
- package/.agents/backend/fm-check-lib.sh +74 -0
- package/.agents/backend/fm-check-register.sh +42 -0
- package/.agents/backend/fm-check-unregister.sh +52 -0
- package/.agents/backend/fm-classify-lib.sh +1770 -0
- package/.agents/backend/fm-claude-stop-autoarm.sh +334 -0
- package/.agents/backend/fm-composer-lib.sh +1416 -0
- package/.agents/backend/fm-config-inherit-lib.sh +1202 -0
- package/.agents/backend/fm-config-push.sh +254 -0
- package/.agents/backend/fm-control-lib.sh +251 -0
- package/.agents/backend/fm-control.sh +878 -0
- package/.agents/backend/fm-crew-state.sh +625 -0
- package/.agents/backend/fm-cursor-lib.sh +243 -0
- package/.agents/backend/fm-decision-hold.sh +232 -0
- package/.agents/backend/fm-doc-audience-check.sh +269 -0
- package/.agents/backend/fm-dod-lib.sh +67 -0
- package/.agents/backend/fm-ensure-agents-md.sh +253 -0
- package/.agents/backend/fm-extension-launch-barrier.mjs +129 -0
- package/.agents/backend/fm-extension.mjs +2577 -0
- package/.agents/backend/fm-extension.sh +16 -0
- package/.agents/backend/fm-ff-lib.sh +420 -0
- package/.agents/backend/fm-fleet-snapshot.sh +1463 -0
- package/.agents/backend/fm-fleet-sync.sh +458 -0
- package/.agents/backend/fm-fleet-view.sh +96 -0
- package/.agents/backend/fm-gate-refuse-lib.sh +102 -0
- package/.agents/backend/fm-guard.sh +242 -0
- package/.agents/backend/fm-harness.sh +195 -0
- package/.agents/backend/fm-herdr-ci-cleanup.sh +115 -0
- package/.agents/backend/fm-herdr-lab.sh +346 -0
- package/.agents/backend/fm-herdr-session-cleanup.sh +337 -0
- package/.agents/backend/fm-home-seed.sh +984 -0
- package/.agents/backend/fm-home-summary-refresh.sh +255 -0
- package/.agents/backend/fm-hook-host-lib.sh +36 -0
- package/.agents/backend/fm-inactive-reconcile.sh +531 -0
- package/.agents/backend/fm-inbox.sh +399 -0
- package/.agents/backend/fm-install-actionlint.sh +84 -0
- package/.agents/backend/fm-install-herdr.sh +96 -0
- package/.agents/backend/fm-install-shellcheck.sh +84 -0
- package/.agents/backend/fm-install-treehouse.sh +95 -0
- package/.agents/backend/fm-kimi-turnend-hook.sh +276 -0
- package/.agents/backend/fm-lease-lib.sh +218 -0
- package/.agents/backend/fm-lease.sh +189 -0
- package/.agents/backend/fm-line-cap-lib.sh +51 -0
- package/.agents/backend/fm-lint-workflows.sh +137 -0
- package/.agents/backend/fm-lint.sh +591 -0
- package/.agents/backend/fm-lock-lib.sh +104 -0
- package/.agents/backend/fm-lock.sh +107 -0
- package/.agents/backend/fm-marker-lib.sh +12 -0
- package/.agents/backend/fm-merge-local.sh +74 -0
- package/.agents/backend/fm-merge-outcome-lib.sh +138 -0
- package/.agents/backend/fm-nm-run-lib.sh +124 -0
- package/.agents/backend/fm-on.sh +125 -0
- package/.agents/backend/fm-operational-input.sh +253 -0
- package/.agents/backend/fm-peek.sh +46 -0
- package/.agents/backend/fm-pending-reply-lib.sh +1409 -0
- package/.agents/backend/fm-pr-check.sh +135 -0
- package/.agents/backend/fm-pr-lib.sh +1016 -0
- package/.agents/backend/fm-pr-merge.sh +707 -0
- package/.agents/backend/fm-pr-poll.sh +110 -0
- package/.agents/backend/fm-primary-scope-lib.sh +33 -0
- package/.agents/backend/fm-procevent-extension-capture.pl +259 -0
- package/.agents/backend/fm-procevent-lavish.sh +628 -0
- package/.agents/backend/fm-procevent-lib.sh +892 -0
- package/.agents/backend/fm-procevent-quota.sh +290 -0
- package/.agents/backend/fm-procevent-remote-reply.sh +577 -0
- package/.agents/backend/fm-procevent-when.sh +504 -0
- package/.agents/backend/fm-procevent.sh +1466 -0
- package/.agents/backend/fm-project-mode.sh +92 -0
- package/.agents/backend/fm-project-origin-lib.sh +180 -0
- package/.agents/backend/fm-promote.sh +282 -0
- package/.agents/backend/fm-public-followup-emit.sh +260 -0
- package/.agents/backend/fm-public-followup-lib.sh +398 -0
- package/.agents/backend/fm-public-followup.sh +1330 -0
- package/.agents/backend/fm-push-transition-lib.sh +168 -0
- package/.agents/backend/fm-quota-axi-lib.sh +93 -0
- package/.agents/backend/fm-quota-choose.sh +384 -0
- package/.agents/backend/fm-remote-delta-read.sh +189 -0
- package/.agents/backend/fm-remote-doctor.sh +800 -0
- package/.agents/backend/fm-remote-entrypoint.sh +193 -0
- package/.agents/backend/fm-remote-file.sh +234 -0
- package/.agents/backend/fm-remote-home-provision.sh +259 -0
- package/.agents/backend/fm-remote-home-seed.sh +259 -0
- package/.agents/backend/fm-remote-inherit-push.sh +90 -0
- package/.agents/backend/fm-remote-inherit.sh +179 -0
- package/.agents/backend/fm-remote-job-lib.sh +1241 -0
- package/.agents/backend/fm-remote-job-reap-orphans.sh +137 -0
- package/.agents/backend/fm-remote-job-worker.sh +1124 -0
- package/.agents/backend/fm-remote-readiness-lib.sh +44 -0
- package/.agents/backend/fm-remote-secondmate-control.sh +340 -0
- package/.agents/backend/fm-review-diff.sh +158 -0
- package/.agents/backend/fm-secondmate-charter-lib.sh +44 -0
- package/.agents/backend/fm-secondmate-nudge-lib.sh +68 -0
- package/.agents/backend/fm-secondmate-parent-lib.sh +70 -0
- package/.agents/backend/fm-secondmate-reconcile.sh +371 -0
- package/.agents/backend/fm-secondmate-registry-lib.sh +311 -0
- package/.agents/backend/fm-secondmate-report.sh +88 -0
- package/.agents/backend/fm-send.sh +1059 -0
- package/.agents/backend/fm-session-lock-lib.sh +176 -0
- package/.agents/backend/fm-session-start.sh +970 -0
- package/.agents/backend/fm-sessionstart-cursor.sh +40 -0
- package/.agents/backend/fm-sessionstart-nudge.sh +45 -0
- package/.agents/backend/fm-sessionstart-run.sh +145 -0
- package/.agents/backend/fm-spawn.sh +3153 -0
- package/.agents/backend/fm-startup-memory-budget-lib.sh +224 -0
- package/.agents/backend/fm-startup-memory-budget.sh +94 -0
- package/.agents/backend/fm-startup-network.sh +642 -0
- package/.agents/backend/fm-stow-cascade.sh +251 -0
- package/.agents/backend/fm-subagent-pretool-check.sh +207 -0
- package/.agents/backend/fm-supervise-daemon.sh +1732 -0
- package/.agents/backend/fm-supervision-instructions.sh +215 -0
- package/.agents/backend/fm-supervision-lib.sh +90 -0
- package/.agents/backend/fm-supervisor-target-lib.sh +78 -0
- package/.agents/backend/fm-tangle-lib.sh +53 -0
- package/.agents/backend/fm-task-inbox-lib.sh +402 -0
- package/.agents/backend/fm-tasks-axi-lib.sh +123 -0
- package/.agents/backend/fm-teardown.sh +2922 -0
- package/.agents/backend/fm-test-isolation-proof.sh +588 -0
- package/.agents/backend/fm-test-run.sh +2191 -0
- package/.agents/backend/fm-timeout-lib.sh +141 -0
- package/.agents/backend/fm-timing-lib.sh +179 -0
- package/.agents/backend/fm-tmux-lib.sh +291 -0
- package/.agents/backend/fm-tool-update-check.sh +898 -0
- package/.agents/backend/fm-trace-context-lib.sh +227 -0
- package/.agents/backend/fm-transition-lib.sh +103 -0
- package/.agents/backend/fm-turnend-guard-cursor.sh +391 -0
- package/.agents/backend/fm-turnend-guard-grok.sh +90 -0
- package/.agents/backend/fm-turnend-guard.sh +432 -0
- package/.agents/backend/fm-update.sh +110 -0
- package/.agents/backend/fm-vendor-auth-probe.sh +190 -0
- package/.agents/backend/fm-voice-client.py +1373 -0
- package/.agents/backend/fm-voice-relay.py +1256 -0
- package/.agents/backend/fm-wake-drain.sh +592 -0
- package/.agents/backend/fm-wake-grant.sh +127 -0
- package/.agents/backend/fm-wake-lib.sh +1849 -0
- package/.agents/backend/fm-watch-arm.sh +602 -0
- package/.agents/backend/fm-watch-checkpoint.sh +109 -0
- package/.agents/backend/fm-watch.sh +1962 -0
- package/.agents/backend/fm-x-dismiss.sh +116 -0
- package/.agents/backend/fm-x-followup.sh +286 -0
- package/.agents/backend/fm-x-lib.sh +1000 -0
- package/.agents/backend/fm-x-link.sh +234 -0
- package/.agents/backend/fm-x-poll.sh +185 -0
- package/.agents/backend/fm-x-reply.sh +385 -0
- package/.agents/backend/fm_voice_frame.py +166 -0
- package/.agents/backend/fm_voice_records.py +574 -0
- package/.agents/backend/model-bridge.py +290 -0
- package/.agents/backend/opencode-go-bridge.py +30 -0
- package/.agents/bus/README.md +12 -0
- package/.agents/bus/messages.json +1 -0
- package/.agents/config/agents.machine.example.yaml +16 -0
- package/.agents/config/agents.yaml +50 -0
- package/.agents/config/agents.yaml.example +72 -0
- package/.agents/config/crew-dispatch.json +22 -0
- package/.agents/config/cron.yaml +9 -0
- package/.agents/config/eindri-dispatch.json +67 -0
- package/.agents/config/eindri-harness +1 -0
- package/.agents/config/startup-memory-budget +1 -0
- package/.agents/config/tailscale-sync.yaml +27 -0
- package/.agents/filebrowser/.filebrowser.json +6 -0
- package/.agents/filebrowser/README.md +11 -0
- package/.agents/gateway/README.md +12 -0
- package/.agents/github/README.md +15 -0
- package/.agents/github/webhooks/.gitkeep +0 -0
- package/.agents/github/workflows/.gitkeep +0 -0
- package/.agents/harness/opencode/plugins/lib/rodd-operational-input.js +37 -0
- package/.agents/harness/opencode/plugins/package.json +4 -0
- package/.agents/harness/opencode/plugins/saga-sessionstart.js +77 -0
- package/.agents/harness/opencode/plugins/syn-cd-check.js +61 -0
- package/.agents/harness/opencode/plugins/syn-pretool-check.js +68 -0
- package/.agents/harness/opencode/plugins/syn-turnend-guard.js +105 -0
- package/.agents/harness/opencode/plugins/syn-watch-arm.js +521 -0
- package/.agents/memory/README.md +46 -0
- package/.agents/memory/kaia.engram +0 -0
- package/.agents/memory/kaia.engram-shm +0 -0
- package/.agents/memory/kaia.engram-wal +0 -0
- package/.agents/memory/runes_audit.md +5 -0
- package/.agents/memory/well/episodes.jsonl +367 -0
- package/.agents/memory/well/workspace.jsonl +27 -0
- package/.agents/migrations/0001-hodd-layout.sh +38 -0
- package/.agents/migrations/0002-a2a-mcp.sh +27 -0
- package/.agents/migrations/0003-private-data-separation.sh +111 -0
- package/.agents/migrations/0004-hoard-and-realms.sh +104 -0
- package/.agents/sandbox/Dockerfile.utgard +19 -0
- package/.agents/sandbox/README.md +14 -0
- package/.agents/sandbox/utgard.config.json +14 -0
- package/.agents/skills/README.md +59 -0
- package/.agents/skills/bragi-marketing/README.md +3 -0
- package/.agents/skills/bragi-marketing/SKILL.md +82 -0
- package/.agents/skills/eindri-homes/README.md +3 -0
- package/.agents/skills/eindri-homes/SKILL.md +291 -0
- package/.agents/skills/eindri-homes/assets/control-plane.md +122 -0
- package/.agents/skills/eindri-homes/assets/dispatch.md +80 -0
- package/.agents/skills/frigg-consent/README.md +3 -0
- package/.agents/skills/frigg-consent/SKILL.md +56 -0
- package/.agents/skills/galdr-ymirsystem/README.md +3 -0
- package/.agents/skills/galdr-ymirsystem/SKILL.md +158 -0
- package/.agents/skills/galdr-ymirsystem/assets/README.md +74 -0
- package/.agents/skills/galdr-ymirsystem/assets/brokk-distro-runtime.md +390 -0
- package/.agents/skills/galdr-ymirsystem/assets/build-method.md +113 -0
- package/.agents/skills/galdr-ymirsystem/assets/build-tool-categories.md +178 -0
- package/.agents/skills/galdr-ymirsystem/assets/eindri-orchestration.md +518 -0
- package/.agents/skills/galdr-ymirsystem/assets/eindri-profiles.md +136 -0
- package/.agents/skills/galdr-ymirsystem/assets/harness-integration/README.md +673 -0
- package/.agents/skills/galdr-ymirsystem/assets/harness-integration/claude-code.md +197 -0
- package/.agents/skills/galdr-ymirsystem/assets/harness-integration/codex.md +191 -0
- package/.agents/skills/galdr-ymirsystem/assets/harness-integration/cursor.md +193 -0
- package/.agents/skills/galdr-ymirsystem/assets/harness-integration/opencode.md +262 -0
- package/.agents/skills/galdr-ymirsystem/assets/harness-integration/pi.md +295 -0
- package/.agents/skills/galdr-ymirsystem/assets/hlidskjalf-ui.md +496 -0
- package/.agents/skills/galdr-ymirsystem/assets/installation.md +571 -0
- package/.agents/skills/galdr-ymirsystem/assets/local-models/HOST-DATA.example.md +72 -0
- package/.agents/skills/galdr-ymirsystem/assets/local-models.md +274 -0
- package/.agents/skills/galdr-ymirsystem/assets/memory-well.md +161 -0
- package/.agents/skills/galdr-ymirsystem/assets/nornir-jobs.md +377 -0
- package/.agents/skills/galdr-ymirsystem/assets/norse-naming.md +325 -0
- package/.agents/skills/galdr-ymirsystem/assets/odrerir-hall.md +129 -0
- package/.agents/skills/galdr-ymirsystem/assets/pi-boot/einherjar-spawn.schema.json +81 -0
- package/.agents/skills/galdr-ymirsystem/assets/pi-boot/herdr-profile.toml +75 -0
- package/.agents/skills/galdr-ymirsystem/assets/pi-boot/pi-profile.yml +96 -0
- package/.agents/skills/galdr-ymirsystem/assets/pi-boot/supervision-tree.yml +163 -0
- package/.agents/skills/galdr-ymirsystem/assets/pi-boot-guide.md +58 -0
- package/.agents/skills/galdr-ymirsystem/assets/porting-upstream-to-norse.md +301 -0
- package/.agents/skills/galdr-ymirsystem/assets/principles.md +385 -0
- package/.agents/skills/galdr-ymirsystem/assets/reference-adoption.md +99 -0
- package/.agents/skills/galdr-ymirsystem/assets/registry.md +379 -0
- package/.agents/skills/galdr-ymirsystem/assets/runtime-compliance.md +463 -0
- package/.agents/skills/galdr-ymirsystem/assets/runtime-components.md +553 -0
- package/.agents/skills/galdr-ymirsystem/assets/smidja.md +175 -0
- package/.agents/skills/galdr-ymirsystem/schemas/toon-schemas.md +190 -0
- package/.agents/skills/galdr-ymirsystem/scripts/README.md +45 -0
- package/.agents/skills/galdr-ymirsystem/scripts/bench-one.sh +248 -0
- package/.agents/skills/galdr-ymirsystem/scripts/compliance-check.sh +360 -0
- package/.agents/skills/galdr-ymirsystem/scripts/gpu-sample.sh +43 -0
- package/.agents/skills/galdr-ymirsystem/scripts/stop-all.sh +34 -0
- package/.agents/skills/galdr-ymirsystem/scripts/toon-check.py +188 -0
- package/.agents/skills/gjallarhorn-relay/README.md +3 -0
- package/.agents/skills/gjallarhorn-relay/SKILL.md +283 -0
- package/.agents/skills/groa-update/SKILL.md +70 -0
- package/.agents/skills/hamr-adapters/README.md +3 -0
- package/.agents/skills/hamr-adapters/SKILL.md +123 -0
- package/.agents/skills/hamr-adapters/references/common/control-and-recovery.md +37 -0
- package/.agents/skills/hamr-adapters/references/common/dispatch.md +32 -0
- package/.agents/skills/hamr-adapters/references/common/model-and-effort.md +42 -0
- package/.agents/skills/hamr-adapters/references/common/primary-hooks.md +40 -0
- package/.agents/skills/hamr-adapters/references/harness/claude.md +55 -0
- package/.agents/skills/hamr-adapters/references/harness/codex.md +43 -0
- package/.agents/skills/hamr-adapters/references/harness/cursor.md +75 -0
- package/.agents/skills/hamr-adapters/references/harness/grok.md +69 -0
- package/.agents/skills/hamr-adapters/references/harness/kimi.md +51 -0
- package/.agents/skills/hamr-adapters/references/harness/muse.md +70 -0
- package/.agents/skills/hamr-adapters/references/harness/opencode.md +42 -0
- package/.agents/skills/hamr-adapters/references/harness/pi.md +56 -0
- package/.agents/skills/herdr-panes/README.md +3 -0
- package/.agents/skills/herdr-panes/SKILL.md +92 -0
- package/.agents/skills/herdr-panes/assets/herdr-backend.md +346 -0
- package/.agents/skills/herdr-panes/assets/tmux-backend.md +115 -0
- package/.agents/skills/hnoss-design/DESIGN.md +19 -0
- package/.agents/skills/hnoss-design/README.md +3 -0
- package/.agents/skills/hnoss-design/SKILL.md +83 -0
- package/.agents/skills/hvild-afk/README.md +3 -0
- package/.agents/skills/hvild-afk/SKILL.md +241 -0
- package/.agents/skills/jord-projects/README.md +3 -0
- package/.agents/skills/jord-projects/SKILL.md +92 -0
- package/.agents/skills/lifecycle/SKILL.md +56 -0
- package/.agents/skills/lifecycle/smoke_test.sh +52 -0
- package/.agents/skills/lifecycle/start.sh +21 -0
- package/.agents/skills/lifecycle/status.sh +35 -0
- package/.agents/skills/lifecycle/stop.sh +16 -0
- package/.agents/skills/muninn-stow/README.md +3 -0
- package/.agents/skills/muninn-stow/SKILL.md +309 -0
- package/.agents/skills/no-mistakes/SKILL.md +379 -0
- package/.agents/skills/nornir-schedule/README.md +3 -0
- package/.agents/skills/nornir-schedule/SKILL.md +25 -0
- package/.agents/skills/nornir-schedule/assets/events.md +137 -0
- package/.agents/skills/nornir-schedule/assets/quota.md +131 -0
- package/.agents/skills/nsr-compliance/README.md +3 -0
- package/.agents/skills/nsr-compliance/SKILL.md +29 -0
- package/.agents/skills/nsr-compliance/assets/nsr/README.md +40 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/RULES/README.md +15 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/RULES/git-workflow.md +18 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/RULES/security.md +22 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/RULES/tech-stack.md +8 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/SKILL.md +71 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/config/core_four.yaml +16 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/gates/check_danger.sh +102 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/gates/check_wiring.sh +69 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/gates/validate_code.sh +29 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/gates/verify_docs.py +66 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/generate.sh +109 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/harness/envelopes/result_envelope.json +14 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/harness/envelopes/task_envelope.json +20 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/harness/runner.py +303 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/telemetry/logger.py +112 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/README.md +18 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/config/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/gates/README.md +12 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/gates/check_env.sh +23 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/gates/check_paths.sh +20 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/gates/check_platform.sh +23 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/harness/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/harness/envelopes/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/installer/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/installer/install.sh +125 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/telemetry/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/README.md +20 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/features/README.md +36 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/features/SKILL-template.md +14 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/README.md +25 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/SKILL.md +13 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/create_branch.sh +6 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/safe_commit.sh +9 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/sync_upstream.sh +6 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/README.md +27 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/SKILL.md +15 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/smoke_test.sh +12 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/start.sh +19 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/status.sh +12 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/stop.sh +15 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/README.md +18 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/config/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/config/core_four.yaml +13 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/README.md +12 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_danger.sh +102 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_env.sh +23 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_paths.sh +20 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_platform.sh +23 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_wiring.sh +69 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/envelopes/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/envelopes/result_envelope.json +14 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/envelopes/task_envelope.json +20 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/runner.py +303 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/installer/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/installer/install.sh +125 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/telemetry/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/telemetry/logger.py +112 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/BEST_PRACTICES/README.md +14 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/BEST_PRACTICES/api.md +17 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/BEST_PRACTICES/compliance-wiring.md +155 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/BEST_PRACTICES/frontend.md +15 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/README.md +23 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/clients/README.md +16 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/clients/template-README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/deploy.sh +49 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/envs/README.md +12 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/envs/development.env.example +17 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/envs/production.env.example +17 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/envs/staging.env.example +17 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/tenants/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/tenants/template.env.example +8 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/README.md +26 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/agent.md +7 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/developers/dev-1.md +20 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/linux.md +9 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/macos.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/shared.md +19 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/windows.md +14 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/HOSTING/README.md +25 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/HOSTING/_template.md +41 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/HOSTING/hosting-1.md +41 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/README.md +21 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/RUNBOOK/README.md +15 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/RUNBOOK/deployment.md +19 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/RUNBOOK/disaster-recovery.md +15 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/RUNBOOK/ops-tasks.md +14 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/features/README.md +16 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/project-skills.md +146 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/research/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/research/software-compliance-research.md +269 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/working-with-agents.md +260 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/AGENTS.md +38 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/ARCHITECTURE.md +36 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/BEST_PRACTICES.md +27 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/CI_CD.md +23 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/FEATURES.md +15 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/README.md +22 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/RULES.md +37 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/STRUCTURE.md +45 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/TECH_STACK.md +28 -0
- package/.agents/skills/nsr-compliance/assets/nsr/scaffold-spec.md +63 -0
- package/.agents/skills/nsr-compliance/assets/nsr/scripts/scaffold.sh +103 -0
- package/.agents/skills/nsr-compliance/assets/nsr/scripts/validate.sh +52 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/SKILL.md +71 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/config/core_four.yaml +16 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/gates/check_danger.sh +102 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/gates/check_wiring.sh +69 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/gates/validate_code.sh +29 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/gates/verify_docs.py +66 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/generate.sh +109 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/harness/envelopes/result_envelope.json +14 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/harness/envelopes/task_envelope.json +20 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/harness/runner.py +303 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/telemetry/logger.py +112 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/README.md +18 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/config/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/gates/README.md +12 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/gates/check_env.sh +23 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/gates/check_paths.sh +20 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/gates/check_platform.sh +23 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/harness/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/harness/envelopes/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/installer/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/installer/install.sh +125 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/telemetry/README.md +11 -0
- package/.agents/skills/pr-ops/README.md +3 -0
- package/.agents/skills/pr-ops/SKILL.md +109 -0
- package/.agents/skills/ratatoskr-a2a/README.md +3 -0
- package/.agents/skills/ratatoskr-a2a/SKILL.md +148 -0
- package/.agents/skills/rules-check-drift/SKILL.md +81 -0
- package/.agents/skills/saga-bearings/README.md +3 -0
- package/.agents/skills/saga-bearings/SKILL.md +26 -0
- package/.agents/skills/saga-bearings/assets/bearings.md +161 -0
- package/.agents/skills/saga-bearings/assets/board-template.html +731 -0
- package/.agents/skills/saga-bearings/assets/recap.md +56 -0
- package/.agents/skills/syn-recovery/README.md +3 -0
- package/.agents/skills/syn-recovery/SKILL.md +54 -0
- package/.agents/skills/tyr-check/README.md +3 -0
- package/.agents/skills/tyr-check/SKILL.md +218 -0
- package/.agents/skills/urdh-hold/README.md +3 -0
- package/.agents/skills/urdh-hold/SKILL.md +25 -0
- package/.agents/skills/urdh-hold/assets/decisions.md +15 -0
- package/.agents/skills/urdh-hold/assets/hold.md +54 -0
- package/.agents/skills/vor-diagnostics/README.md +3 -0
- package/.agents/skills/vor-diagnostics/SKILL.md +68 -0
- package/.agents/skills/ymir-host/README.md +3 -0
- package/.agents/skills/ymir-host/SKILL.md +34 -0
- package/.agents/skills/ymir-host/assets/desktop.md +36 -0
- package/.agents/skills/ymir-host/assets/omarchy.md +297 -0
- package/.agents/skills/ymir-host/assets/runbooks.md +15 -0
- package/.agents/skills/ymir-host/assets/thjazi.md +220 -0
- package/.agents/skills/ymir-host/assets/update.md +64 -0
- package/.agents/tests/assets/board-render-harness.mjs +117 -0
- package/.agents/tests/cmux-test-safety.sh +51 -0
- package/.agents/tests/fixtures.sh +291 -0
- package/.agents/tests/fm-afk-inject-e2e.test.sh +428 -0
- package/.agents/tests/fm-afk-inject-herdr-e2e.test.sh +536 -0
- package/.agents/tests/fm-afk-launch.test.sh +961 -0
- package/.agents/tests/fm-afk-pi-herdr-return-e2e.test.sh +297 -0
- package/.agents/tests/fm-afk-return.test.sh +283 -0
- package/.agents/tests/fm-arm-pretool-check.test.sh +482 -0
- package/.agents/tests/fm-ask-user-authority.test.sh +42 -0
- package/.agents/tests/fm-backend-autodetect-smoke.test.sh +176 -0
- package/.agents/tests/fm-backend-cmux-smoke.test.sh +188 -0
- package/.agents/tests/fm-backend-cmux.test.sh +1166 -0
- package/.agents/tests/fm-backend-herdr-eventwait-smoke.test.sh +136 -0
- package/.agents/tests/fm-backend-herdr-eventwait.test.py +106 -0
- package/.agents/tests/fm-backend-herdr-focus-flash-e2e.test.sh +409 -0
- package/.agents/tests/fm-backend-herdr-launcher-workspace-e2e.test.sh +437 -0
- package/.agents/tests/fm-backend-herdr-presentation-e2e.test.sh +1424 -0
- package/.agents/tests/fm-backend-herdr-prune-safety-e2e.test.sh +180 -0
- package/.agents/tests/fm-backend-herdr-respawn-idem-e2e.test.sh +182 -0
- package/.agents/tests/fm-backend-herdr-smoke.test.sh +355 -0
- package/.agents/tests/fm-backend-herdr-workspace-per-home-e2e.test.sh +251 -0
- package/.agents/tests/fm-backend-herdr.test.sh +4606 -0
- package/.agents/tests/fm-backend-orca.test.sh +1357 -0
- package/.agents/tests/fm-backend-tmux-smoke.test.sh +173 -0
- package/.agents/tests/fm-backend-zellij-smoke.test.sh +205 -0
- package/.agents/tests/fm-backend-zellij.test.sh +1360 -0
- package/.agents/tests/fm-backend.test.sh +1142 -0
- package/.agents/tests/fm-backlog-atomicity.test.sh +2302 -0
- package/.agents/tests/fm-backlog-handoff.test.sh +1360 -0
- package/.agents/tests/fm-bearings-board-render.test.sh +135 -0
- package/.agents/tests/fm-bearings-board.test.sh +414 -0
- package/.agents/tests/fm-bearings-snapshot.test.sh +1990 -0
- package/.agents/tests/fm-bootstrap-network-parallel.test.sh +316 -0
- package/.agents/tests/fm-bootstrap.test.sh +1178 -0
- package/.agents/tests/fm-branch-supervision.test.sh +552 -0
- package/.agents/tests/fm-brief.test.sh +785 -0
- package/.agents/tests/fm-busy-adapter-wiring.test.sh +324 -0
- package/.agents/tests/fm-busy-state.test.sh +465 -0
- package/.agents/tests/fm-calm-pi-extension.test.sh +3979 -0
- package/.agents/tests/fm-captain-hold-lifecycle.test.sh +1187 -0
- package/.agents/tests/fm-cd-pretool-check.test.sh +400 -0
- package/.agents/tests/fm-check-unregister.test.sh +198 -0
- package/.agents/tests/fm-classify-corr-token.test.sh +543 -0
- package/.agents/tests/fm-classify-decision-key.test.sh +340 -0
- package/.agents/tests/fm-claude-stop-autoarm-live-e2e.test.sh +164 -0
- package/.agents/tests/fm-claude-stop-autoarm.test.sh +1190 -0
- package/.agents/tests/fm-cmux-claude-composer-live-e2e.test.sh +110 -0
- package/.agents/tests/fm-codex-continuity-live-e2e.test.sh +55 -0
- package/.agents/tests/fm-composer-ghost.test.sh +716 -0
- package/.agents/tests/fm-composer-lib.test.sh +666 -0
- package/.agents/tests/fm-composer-matrix-live-e2e.test.sh +220 -0
- package/.agents/tests/fm-control-herdr-smoke.test.sh +149 -0
- package/.agents/tests/fm-control-relaunch.test.sh +1530 -0
- package/.agents/tests/fm-control.test.sh +910 -0
- package/.agents/tests/fm-crew-state.test.sh +1610 -0
- package/.agents/tests/fm-cursor-harness.test.sh +404 -0
- package/.agents/tests/fm-cursor-primary-live-e2e.test.sh +217 -0
- package/.agents/tests/fm-cursor-primary.test.sh +708 -0
- package/.agents/tests/fm-daemon.test.sh +2740 -0
- package/.agents/tests/fm-documentation-audiences.test.sh +141 -0
- package/.agents/tests/fm-ensure-agents-md.test.sh +371 -0
- package/.agents/tests/fm-extension-binding.test.sh +2187 -0
- package/.agents/tests/fm-fleet-snapshot-view.test.sh +816 -0
- package/.agents/tests/fm-fleet-sync.test.sh +721 -0
- package/.agents/tests/fm-gate-refuse.test.sh +356 -0
- package/.agents/tests/fm-gitignore-config.test.sh +89 -0
- package/.agents/tests/fm-gotmp.test.sh +230 -0
- package/.agents/tests/fm-grok-continuity-live-e2e.test.sh +112 -0
- package/.agents/tests/fm-grok-harness.test.sh +117 -0
- package/.agents/tests/fm-grok-stop-live-e2e.test.sh +219 -0
- package/.agents/tests/fm-guard-stale-banner.test.sh +709 -0
- package/.agents/tests/fm-harness-adapter-instructions-live-e2e.test.sh +134 -0
- package/.agents/tests/fm-harness-adapter-references.test.sh +30 -0
- package/.agents/tests/fm-harness-liveness-drift-live-e2e.test.sh +151 -0
- package/.agents/tests/fm-herdr-lab.test.sh +243 -0
- package/.agents/tests/fm-herdr-session-cleanup-e2e.test.sh +146 -0
- package/.agents/tests/fm-herdr-session-cleanup.test.sh +329 -0
- package/.agents/tests/fm-herdr-submit-confirm-live-e2e.test.sh +125 -0
- package/.agents/tests/fm-herdr-version-floor-live-e2e.test.sh +144 -0
- package/.agents/tests/fm-home-summary-refresh.test.sh +971 -0
- package/.agents/tests/fm-inactive-reconcile.test.sh +485 -0
- package/.agents/tests/fm-kimi-harness.test.sh +687 -0
- package/.agents/tests/fm-lint-workflows.test.sh +532 -0
- package/.agents/tests/fm-lint.test.sh +1023 -0
- package/.agents/tests/fm-muse-harness.test.sh +932 -0
- package/.agents/tests/fm-muse-signals-live-e2e.test.sh +205 -0
- package/.agents/tests/fm-no-mistakes-required.test.sh +72 -0
- package/.agents/tests/fm-on.test.sh +507 -0
- package/.agents/tests/fm-opencode-primary-live-e2e.test.sh +357 -0
- package/.agents/tests/fm-operational-input.test.sh +160 -0
- package/.agents/tests/fm-peek-remote.test.sh +110 -0
- package/.agents/tests/fm-pending-reply.test.sh +1288 -0
- package/.agents/tests/fm-pi-branch-extension.test.sh +3182 -0
- package/.agents/tests/fm-pi-branch-live-e2e.test.sh +527 -0
- package/.agents/tests/fm-pi-primary-live-e2e.test.sh +345 -0
- package/.agents/tests/fm-pi-primary-types.test.sh +68 -0
- package/.agents/tests/fm-pi-watch-extension.test.sh +2843 -0
- package/.agents/tests/fm-pr-check-security.test.sh +2140 -0
- package/.agents/tests/fm-pr-merge.test.sh +2135 -0
- package/.agents/tests/fm-procevent-quota.test.sh +225 -0
- package/.agents/tests/fm-procevent-when.test.sh +406 -0
- package/.agents/tests/fm-procevent.test.sh +1745 -0
- package/.agents/tests/fm-project-origin.test.sh +110 -0
- package/.agents/tests/fm-public-followup.test.sh +2272 -0
- package/.agents/tests/fm-quota-array-dispatch-live-e2e.test.sh +526 -0
- package/.agents/tests/fm-quota-choose.test.sh +626 -0
- package/.agents/tests/fm-remote-backlog-handoff.test.sh +453 -0
- package/.agents/tests/fm-remote-doctor.test.sh +625 -0
- package/.agents/tests/fm-remote-entrypoint.test.sh +59 -0
- package/.agents/tests/fm-remote-job-orphan-reap.test.sh +205 -0
- package/.agents/tests/fm-remote-job.test.sh +768 -0
- package/.agents/tests/fm-remote-reply.test.sh +520 -0
- package/.agents/tests/fm-remote-secondmate-lifecycle-e2e.test.sh +1256 -0
- package/.agents/tests/fm-remote-secondmate-parent-binding.test.sh +326 -0
- package/.agents/tests/fm-remote-secondmate-trace-context.test.sh +310 -0
- package/.agents/tests/fm-remote-transport-lanes.test.sh +431 -0
- package/.agents/tests/fm-review-diff.test.sh +176 -0
- package/.agents/tests/fm-secondmate-harness.test.sh +2600 -0
- package/.agents/tests/fm-secondmate-lifecycle-e2e.test.sh +259 -0
- package/.agents/tests/fm-secondmate-liveness.test.sh +559 -0
- package/.agents/tests/fm-secondmate-reconcile.test.sh +732 -0
- package/.agents/tests/fm-secondmate-safety.test.sh +2972 -0
- package/.agents/tests/fm-secondmate-sync.test.sh +913 -0
- package/.agents/tests/fm-send-inbox-doorbell-live-e2e.test.sh +206 -0
- package/.agents/tests/fm-send-inbox.test.sh +352 -0
- package/.agents/tests/fm-send-popup-settle.test.sh +167 -0
- package/.agents/tests/fm-send-remote-delivery.test.sh +796 -0
- package/.agents/tests/fm-send-resolve-key.test.sh +551 -0
- package/.agents/tests/fm-send-secondmate-marker-herdr-e2e.test.sh +187 -0
- package/.agents/tests/fm-send-secondmate-marker.test.sh +278 -0
- package/.agents/tests/fm-send-settle.test.sh +147 -0
- package/.agents/tests/fm-send-strict.test.sh +241 -0
- package/.agents/tests/fm-session-lock-ancestry.test.sh +365 -0
- package/.agents/tests/fm-session-start.test.sh +2515 -0
- package/.agents/tests/fm-sessionstart-hook-live-e2e.test.sh +631 -0
- package/.agents/tests/fm-sessionstart-instruction-refresh-live-e2e.test.sh +230 -0
- package/.agents/tests/fm-sessionstart-nudge.test.sh +1039 -0
- package/.agents/tests/fm-shared-captain-inheritance.test.sh +404 -0
- package/.agents/tests/fm-spawn-batch.test.sh +148 -0
- package/.agents/tests/fm-spawn-dispatch-profile.test.sh +827 -0
- package/.agents/tests/fm-spawn-pool-base-freshen.test.sh +440 -0
- package/.agents/tests/fm-spawn-worktree-settle.test.sh +147 -0
- package/.agents/tests/fm-startup-memory-budget.test.sh +333 -0
- package/.agents/tests/fm-startup-network.test.sh +712 -0
- package/.agents/tests/fm-stow-cascade.test.sh +370 -0
- package/.agents/tests/fm-subagent-pretool-check.test.sh +291 -0
- package/.agents/tests/fm-supervision-events.test.sh +156 -0
- package/.agents/tests/fm-supervision-instructions.test.sh +189 -0
- package/.agents/tests/fm-tangle-guard.test.sh +277 -0
- package/.agents/tests/fm-task-delivery.test.sh +420 -0
- package/.agents/tests/fm-task-inbox.test.sh +513 -0
- package/.agents/tests/fm-teardown-endpoint-safety.test.sh +374 -0
- package/.agents/tests/fm-teardown.test.sh +2665 -0
- package/.agents/tests/fm-test-fixture-cleanup.test.sh +172 -0
- package/.agents/tests/fm-test-fixtures.test.sh +132 -0
- package/.agents/tests/fm-test-isolation-proof.test.sh +278 -0
- package/.agents/tests/fm-test-run.test.sh +1196 -0
- package/.agents/tests/fm-tmux-agent-liveness.test.sh +354 -0
- package/.agents/tests/fm-tmux-submit-busy.test.sh +340 -0
- package/.agents/tests/fm-tool-update-check.test.sh +1044 -0
- package/.agents/tests/fm-trace-context-lib.test.sh +253 -0
- package/.agents/tests/fm-trace-context-spawn.test.sh +581 -0
- package/.agents/tests/fm-transition-lib.test.sh +54 -0
- package/.agents/tests/fm-turnend-guard.test.sh +1822 -0
- package/.agents/tests/fm-update.test.sh +304 -0
- package/.agents/tests/fm-vendor-auth-probe.test.sh +395 -0
- package/.agents/tests/fm-voice-relay.test.sh +4741 -0
- package/.agents/tests/fm-wake-daemon-lifecycle-e2e.test.sh +171 -0
- package/.agents/tests/fm-wake-drain-open-decisions-cursor.test.sh +356 -0
- package/.agents/tests/fm-wake-drain-open-decisions.test.sh +226 -0
- package/.agents/tests/fm-wake-drain-unread-status.test.sh +379 -0
- package/.agents/tests/fm-wake-queue.test.sh +1224 -0
- package/.agents/tests/fm-watch-arm.test.sh +821 -0
- package/.agents/tests/fm-watch-checkpoint.test.sh +87 -0
- package/.agents/tests/fm-watch-recovery-loop.test.sh +223 -0
- package/.agents/tests/fm-watch-triage.test.sh +3889 -0
- package/.agents/tests/fm-watcher-lock.test.sh +1133 -0
- package/.agents/tests/fm-x-mode.test.sh +3042 -0
- package/.agents/tests/gleipnir-guard-pretool-check.test.sh +51 -0
- package/.agents/tests/gleipnir-machine-lock.test.sh +130 -0
- package/.agents/tests/herdr-test-safety.sh +42 -0
- package/.agents/tests/lib.sh +315 -0
- package/.agents/tests/remote-herdr-fixture.sh +125 -0
- package/.agents/tests/secondmate-helpers.sh +193 -0
- package/.agents/tests/smoke.test.sh +93 -0
- package/.agents/tests/wake-helpers.sh +338 -0
- package/.agents/tests/zellij-test-safety.sh +60 -0
- package/.agents/tools/README.md +10 -0
- package/.agents/tools/bin/tasks-cli +267 -0
- package/.agents/tools/tasks-cli.ts +216 -0
- package/AGENTS.md +454 -0
- package/CHANGELOG.md +881 -0
- package/LICENSE +1 -1
- package/NOTICE +63 -0
- package/README.md +113 -39
- package/RULES/01-domains.md +51 -0
- package/RULES/02-agents.md +78 -0
- package/RULES/03-houses.md +61 -0
- package/RULES/04-hoard.md +65 -0
- package/RULES/05-platforms.md +67 -0
- package/RULES/06-append-only.md +58 -0
- package/RULES/07-config.md +45 -0
- package/RULES/08-delivery-gate.md +75 -0
- package/RULES/README.md +20 -0
- package/bin/README.md +107 -0
- package/bin/a2a-mcp.sh +98 -0
- package/bin/a2a-serve.py +103 -0
- package/bin/a2a-serve.sh +8 -0
- package/bin/a2a-talk.sh +50 -0
- package/bin/a2abridge-ensure.sh +108 -0
- package/bin/agent-run.sh +43 -0
- package/bin/agents-config.sh +233 -0
- package/bin/apodex-smoke-test.sh +92 -0
- package/bin/bifrost-bridge.sh +112 -0
- package/bin/bifrost-ingress.sh +77 -0
- package/bin/bootstrap-macos.sh +107 -0
- package/bin/bootstrap-windows.ps1 +112 -0
- package/bin/branch-guard.sh +64 -0
- package/bin/brokk +73 -0
- package/bin/brokk-classify-lib.sh +1770 -0
- package/bin/brokk-lease-lib.sh +222 -0
- package/bin/brokk-lease.sh +193 -0
- package/bin/brokk-lint.sh +65 -0
- package/bin/brokk-send.sh +38 -0
- package/bin/brokk-update.sh +9 -0
- package/bin/brokk-wake-grant.sh +127 -0
- package/bin/brokk-wake-lib.sh +1849 -0
- package/bin/changelog-guard.sh +165 -0
- package/bin/crash-sense.sh +160 -0
- package/bin/desktop-place.sh +224 -0
- package/bin/docs-guard.sh +39 -0
- package/bin/editor-place.sh +207 -0
- package/bin/eindri-acclaim.sh +34 -0
- package/bin/eindri-control.sh +28 -0
- package/bin/eindri-role.sh +83 -0
- package/bin/eindri-seen.sh +41 -0
- package/bin/eindri-send.sh +15 -0
- package/bin/eindri-start.sh +85 -0
- package/bin/eindri-watch.sh +57 -0
- package/bin/einherjar-spawn.sh +576 -0
- package/bin/eir-doctor.sh +112 -0
- package/bin/erindi-brief.sh +271 -0
- package/bin/fleet-apply.sh +68 -0
- package/bin/github-deploy.sh +81 -0
- package/bin/gjallarhorn-expose.sh +102 -0
- package/bin/gjallarhorn-notify.sh +58 -0
- package/bin/gjallarhorn-purge.sh +54 -0
- package/bin/gjallarhorn-tunnel.sh +72 -0
- package/bin/gleipnir-lock-lib.sh +284 -0
- package/bin/groa-update.sh +122 -0
- package/bin/hall-snapshot.sh +92 -0
- package/bin/hamr-harness.sh +246 -0
- package/bin/heimdall-ssh-keys.sh +374 -0
- package/bin/herdr-agents.py +44 -0
- package/bin/herdr-ensure.sh +104 -0
- package/bin/herdr-run.sh +431 -0
- package/bin/hermes-ensure.sh +88 -0
- package/bin/hoard-lib.sh +25 -0
- package/bin/hodd.sh +78 -0
- package/bin/host-sense.sh +199 -0
- package/bin/huginn-research-worker.sh +108 -0
- package/bin/local-model-lock.sh +51 -0
- package/bin/mimir-bridge.py +226 -0
- package/bin/mimir-bridge.sh +87 -0
- package/bin/mimir-ingest.sh +131 -0
- package/bin/mimir.sh +113 -0
- package/bin/mjollnir-webhook.sh +59 -0
- package/bin/mjollnir.sh +85 -0
- package/bin/model-hardware.sh +82 -0
- package/bin/model-resolve.sh +147 -0
- package/bin/models-detect.sh +178 -0
- package/bin/nornir-cron-start.sh +162 -0
- package/bin/nornir-job-daily-briefing.sh +191 -0
- package/bin/nornir-job-git-sync.sh +152 -0
- package/bin/nornir-job-memory-housekeeping.sh +114 -0
- package/bin/nornir-job-observer.sh +166 -0
- package/bin/nornir-job-skillopt-sleep.sh +76 -0
- package/bin/omarchy-hook-install.sh +60 -0
- package/bin/omarchy-install.sh +148 -0
- package/bin/omarchy-plugins.sh +174 -0
- package/bin/omarchy-sense.sh +149 -0
- package/bin/perm-guard.sh +30 -0
- package/bin/pi-agent.sh +68 -0
- package/bin/pi-ensure.sh +77 -0
- package/bin/pi-local.sh +37 -0
- package/bin/pi-seat.sh +63 -0
- package/bin/prereq-ensure.sh +166 -0
- package/bin/private-guard.sh +38 -0
- package/bin/project-git.sh +55 -0
- package/bin/public-guard.sh +70 -0
- package/bin/ratatoskr.sh +49 -0
- package/bin/realm-lib.sh +32 -0
- package/bin/repo-scrub.sh +62 -0
- package/bin/rodd-operational-input.sh +250 -0
- package/bin/runes-append.sh +198 -0
- package/bin/saga-session-start.sh +172 -0
- package/bin/saga-sessionstart-run.sh +79 -0
- package/bin/saga-wake-drain.sh +41 -0
- package/bin/secret-guard.sh +63 -0
- package/bin/sessrumnir-ensure.sh +100 -0
- package/bin/sessrumnir-sync.sh +237 -0
- package/bin/sessrumnir.sh +91 -0
- package/bin/skillopt-setup.sh +76 -0
- package/bin/skuld-branch-outcome.sh +203 -0
- package/bin/skuld-branch-prompt.sh +101 -0
- package/bin/smidja-bootstrap.sh +90 -0
- package/bin/smidja-observe.sh +86 -0
- package/bin/syn-arm-pretool-check.sh +57 -0
- package/bin/syn-asset-pretool-check.sh +76 -0
- package/bin/syn-cd-pretool-check.sh +28 -0
- package/bin/syn-guard-pretool-check.sh +83 -0
- package/bin/syn-turnend-guard.sh +36 -0
- package/bin/syn-watch-arm.sh +99 -0
- package/bin/tailscale-sync.sh +190 -0
- package/bin/telegram-bot.sh +69 -0
- package/bin/toolchain.sh +74 -0
- package/bin/utgard.sh +111 -0
- package/bin/valhalla.sh +115 -0
- package/bin/valknut-load.sh +260 -0
- package/bin/vor-crew-state.sh +124 -0
- package/bin/wedge-notify.sh +47 -0
- package/bin/workspace-provision.sh +80 -0
- package/bin/workspace-rag.sh +150 -0
- package/bin/wyrd-db.sh +47 -0
- package/bin/yggdrasil.sh +152 -0
- package/bin/ymir-edit.sh +145 -0
- package/bin/ymir-install.sh +641 -0
- package/bin/ymir-invite.sh +93 -0
- package/bin/ymir-isolation.sh +88 -0
- package/bin/ymir-migrate.sh +61 -0
- package/bin/ymir-platform.sh +348 -0
- package/bin/ymir-say.sh +97 -0
- package/bin/ymir-setup-auth.sh +108 -0
- package/bin/ymir-validate.sh +173 -0
- package/bin/ymir.js +74 -16
- package/docs/Architecture.md +339 -0
- package/docs/design.md +351 -0
- package/docs/installations/README.md +63 -0
- package/docs/installations/ymir-home.md +93 -0
- package/docs/integration.md +105 -0
- package/docs/lore.md +1056 -0
- package/docs/research/agent-harnesses.md +290 -0
- package/docs/runbooks/README.md +19 -0
- package/docs/runbooks/a2a.md +91 -0
- package/docs/runbooks/agent-permissions.md +99 -0
- package/docs/runbooks/agents.md +57 -0
- package/docs/runbooks/models.md +69 -0
- package/docs/runbooks/realm-onboarding.md +60 -0
- package/docs/runbooks/secrets-and-hoard.md +60 -0
- package/docs/runbooks/updates-and-migrations.md +110 -0
- package/docs/runbooks/worktrees-isolation.md +72 -0
- package/docs/session-start.md +105 -0
- package/docs/skillopt-integration.md +321 -0
- package/docs/sync-system.md +66 -0
- package/docs/workspaces.md +104 -0
- package/docs/ymir-rut.md +260 -0
- package/package.json +44 -14
- package/packaging/build.sh +74 -0
- package/packaging/macos/Ymir Installer.command +43 -0
- package/packaging/windows/ymir-setup.nsi +74 -0
- package/scripts/README.md +22 -0
- package/scripts/electron.sh +210 -0
- package/scripts/start.sh +167 -0
- package/scripts/stop.sh +113 -0
- package/install.sh +0 -35
|
@@ -0,0 +1,574 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""fm_voice_records.py - what the voice agent is allowed to know, and how it hands work over.
|
|
3
|
+
|
|
4
|
+
The voice agent answers status questions from firstmate's durable records and
|
|
5
|
+
queues everything else. This module owns both halves, because both halves are
|
|
6
|
+
where a mistake is expensive: one sends the captain's records to a model in
|
|
7
|
+
another region, and the other writes to firstmate's wake queue.
|
|
8
|
+
|
|
9
|
+
WHAT IS NEVER READ. Two whole classes of record are excluded at every scope,
|
|
10
|
+
not filtered at the end:
|
|
11
|
+
|
|
12
|
+
Done history, because a spoken "what is happening" answer is about open work,
|
|
13
|
+
and the finished items are where old engagements accumulate.
|
|
14
|
+
Free-form note bodies under a task, because they are long, they are written
|
|
15
|
+
for a reader with the whole file in front of them, and they are where
|
|
16
|
+
commercial detail gets quoted.
|
|
17
|
+
|
|
18
|
+
Only open task lines and this home's own runtime records are ever assembled.
|
|
19
|
+
That is a confidentiality boundary as much as a brevity one. Verified on the
|
|
20
|
+
captain's live records on 2026-08-21: every occurrence of the one engagement
|
|
21
|
+
identifier those records contain sits in Done history or a note body, so
|
|
22
|
+
nothing in a full status answer named a customer. tests/fm-voice-relay.test.sh
|
|
23
|
+
holds that boundary as an executable check, so widening the reader later fails
|
|
24
|
+
the test rather than quietly widening what is sent.
|
|
25
|
+
|
|
26
|
+
Runtime records outlive the work they describe: a task keeps its state/<id>.meta
|
|
27
|
+
until teardown removes it, which happens separately from marking the item done.
|
|
28
|
+
Two readings here treat that differently, on purpose.
|
|
29
|
+
|
|
30
|
+
Pull requests, the count and the list, cover OPEN ids only. They name work, and
|
|
31
|
+
they feed the deny decision, which needs an open item to take a title from. A
|
|
32
|
+
finished task's pull request is therefore not counted and not named, and that
|
|
33
|
+
lost count is a deliberate cost: the alternative names finished work and puts
|
|
34
|
+
it out of reach of the deny list, which has no title to match without an open
|
|
35
|
+
item to take it from.
|
|
36
|
+
|
|
37
|
+
The worker count and the state histogram cover every live runtime record,
|
|
38
|
+
finished ids included, because a task with a meta file still on disk is still
|
|
39
|
+
on deck and still needs tearing down. That is the question those two figures
|
|
40
|
+
answer, and it is the same meaning bin/fm-inbox.sh gives "workers" in the human
|
|
41
|
+
rendering. Neither can carry record free text: one is an integer, and the
|
|
42
|
+
other's keys are the state verb folded through the closed set below.
|
|
43
|
+
|
|
44
|
+
READ SCOPE. config/voice-read-scope selects what a status answer may contain:
|
|
45
|
+
|
|
46
|
+
counts (the default, and the value used when the file is absent)
|
|
47
|
+
Counts, states and one basis note, with no record free text assembled at
|
|
48
|
+
all. Safe by construction rather than by filtering: the agent can say how
|
|
49
|
+
much is waiting without saying what it is. This is the default because a
|
|
50
|
+
home that has configured nothing has granted nothing, and sending task
|
|
51
|
+
identifiers, titles and pull request links to a model in another region is
|
|
52
|
+
not something to inherit from somebody else's settings file.
|
|
53
|
+
|
|
54
|
+
full
|
|
55
|
+
Counts plus the identifiers, titles and pull request links of open work.
|
|
56
|
+
A home widens to this by writing `full` into config/voice-read-scope,
|
|
57
|
+
which is the access being granted deliberately by the captain whose
|
|
58
|
+
records they are.
|
|
59
|
+
|
|
60
|
+
DENY LIST. config/voice-read-deny holds anything that must never leave this
|
|
61
|
+
host even in full scope: one plain case-insensitive substring per line, `#`
|
|
62
|
+
starts a comment, blank lines ignored. Substrings rather than regular
|
|
63
|
+
expressions, because a confidentiality list is the wrong place for a pattern
|
|
64
|
+
that can match more or less than it looks like it matches. Each open item is
|
|
65
|
+
matched once, against its identifier, its title, its tag values and its pull
|
|
66
|
+
request link together, and a match is then withheld from every list it could
|
|
67
|
+
have appeared in and reduced to a withheld count. One decision per item rather
|
|
68
|
+
than one per list, because an item named in any list is an item that left this
|
|
69
|
+
host. The agent still says how much is waiting without saying what it is. The
|
|
70
|
+
file is optional and an absent file means an empty list; it exists so that a
|
|
71
|
+
future open task carrying a customer name can be excluded in one line rather
|
|
72
|
+
than by turning the whole feature down.
|
|
73
|
+
|
|
74
|
+
WORKER STATE. This module reports the last recorded event verb, which is
|
|
75
|
+
history rather than a live check, and labels it that way in its own output so
|
|
76
|
+
the model cannot present it as current truth. bin/fm-crew-state.sh remains the
|
|
77
|
+
owner of real current-state reconciliation and is far too slow for a spoken
|
|
78
|
+
answer. The verb is folded through the closed STATE_VERBS vocabulary below, and
|
|
79
|
+
anything outside it becomes "note": a status line is free text, and this verb is
|
|
80
|
+
the only thing derived from a record that a counts-scope answer says out loud.
|
|
81
|
+
|
|
82
|
+
bin/fm-inbox.sh `status` is the human rendering of the same records and stays
|
|
83
|
+
the owner of that. This module exists because a spoken answer needs a machine
|
|
84
|
+
shape and a read scope that the human rendering has no reason to carry.
|
|
85
|
+
|
|
86
|
+
Usage:
|
|
87
|
+
fm_voice_records.py status [--home <dir>] [--scope counts|full]
|
|
88
|
+
fm_voice_records.py queue <text>... [--home <dir>]
|
|
89
|
+
|
|
90
|
+
Both subcommands print JSON, which is exactly what the relay hands to the model
|
|
91
|
+
as a tool result, so the shell form is the same interface the relay uses.
|
|
92
|
+
"""
|
|
93
|
+
|
|
94
|
+
import argparse
|
|
95
|
+
import json
|
|
96
|
+
import os
|
|
97
|
+
import re
|
|
98
|
+
import subprocess
|
|
99
|
+
import sys
|
|
100
|
+
|
|
101
|
+
SCOPE_COUNTS = "counts"
|
|
102
|
+
SCOPE_FULL = "full"
|
|
103
|
+
SCOPES = (SCOPE_FULL, SCOPE_COUNTS)
|
|
104
|
+
SCOPE_DEFAULT = SCOPE_COUNTS
|
|
105
|
+
|
|
106
|
+
BASIS = "Last recorded event, which is history and not a live check."
|
|
107
|
+
|
|
108
|
+
# A spoken answer names a few things and gives a count for the rest. Every row
|
|
109
|
+
# sent is input tokens the model reads before it starts speaking, and this whole
|
|
110
|
+
# build exists to keep that delay honest, so the lists are capped rather than
|
|
111
|
+
# complete. A complete list is a screen, not a sentence.
|
|
112
|
+
DETAIL_LIMIT = 5
|
|
113
|
+
|
|
114
|
+
ITEM = re.compile(r"^- \[(?P<done>[ x])\] (?P<id>\S+) - (?P<rest>.*)$")
|
|
115
|
+
TAG = re.compile(r"\((?P<key>[a-z-]+): (?P<value>[^)]*)\)")
|
|
116
|
+
# (since 2026-08-21) and (done 2026-08-21) carry no colon, so the tag pattern
|
|
117
|
+
# leaves them in the title. A date read aloud in the middle of a sentence is
|
|
118
|
+
# noise, so they come out too.
|
|
119
|
+
DATE_TAG = re.compile(r"\((?:since|done) [0-9-]+\)")
|
|
120
|
+
|
|
121
|
+
# The only backlog sections this module will parse. Done history is skipped
|
|
122
|
+
# before a line is even split, so widening the answer cannot reach it by
|
|
123
|
+
# accident. See "WHAT IS NEVER READ" above.
|
|
124
|
+
READ_SECTIONS = ("in flight", "queued")
|
|
125
|
+
|
|
126
|
+
# The states a worker is asked to report, and the two more that close a decision.
|
|
127
|
+
# bin/fm-brief.sh states the first six to every crewmate and bin/fm-classify-lib.sh
|
|
128
|
+
# owns resolved and captain-held; this module only recognises them.
|
|
129
|
+
#
|
|
130
|
+
# A CLOSED set, not a shape. A status line is free text appended by a crewmate,
|
|
131
|
+
# and the verb taken off the front of it is the one record-derived string that
|
|
132
|
+
# reaches a counts-scope answer, where there are no titles or links for a deny
|
|
133
|
+
# list to filter. So an unrecognised token is reported as a note instead of being
|
|
134
|
+
# spoken, exactly as a malformed one already was; otherwise a crewmate writing
|
|
135
|
+
# "acmecorp-migration: waiting on their review" would put that word in front of a
|
|
136
|
+
# model in another region, with nothing in config/voice-read-deny able to stop it.
|
|
137
|
+
STATE_VERBS = ("working", "needs-decision", "blocked", "paused", "done",
|
|
138
|
+
"failed", "resolved", "captain-held")
|
|
139
|
+
NOTE_VERB = "note"
|
|
140
|
+
|
|
141
|
+
# Enough tail to hold the last line of a status log. These logs are append-only
|
|
142
|
+
# and grow for the life of a task, while every spoken question reads one per
|
|
143
|
+
# worker, so the read is bounded and seeks rather than scanning from the top.
|
|
144
|
+
STATUS_TAIL_BYTES = 8192
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
class RecordError(Exception):
|
|
148
|
+
"""The records or the read-scope configuration cannot be used as asked."""
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def default_home():
|
|
152
|
+
"""Return the operational home, matching bin/fm-inbox.sh's resolution."""
|
|
153
|
+
env = os.environ.get("FM_HOME")
|
|
154
|
+
if env:
|
|
155
|
+
return env
|
|
156
|
+
return os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def state_dir(home):
|
|
160
|
+
"""Return the runtime state directory, resolved as bin/fm-inbox.sh resolves it.
|
|
161
|
+
|
|
162
|
+
fm-inbox.sh reads ${FM_STATE_OVERRIDE:-$FM_HOME/state}, and the handover
|
|
163
|
+
below queues through fm-inbox.sh with the ambient environment. A reader that
|
|
164
|
+
ignored the override would count notes in one directory while the queue wrote
|
|
165
|
+
them to another, so the agent would tell the captain their request was queued
|
|
166
|
+
and then, asked what is waiting, report nothing.
|
|
167
|
+
"""
|
|
168
|
+
override = os.environ.get("FM_STATE_OVERRIDE")
|
|
169
|
+
if override:
|
|
170
|
+
return override
|
|
171
|
+
return os.path.join(home, "state")
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def data_dir(home):
|
|
175
|
+
"""Return the durable records directory, the other half of the same pair.
|
|
176
|
+
|
|
177
|
+
Every script that sets FM_DATA_OVERRIDE for a child sets FM_STATE_OVERRIDE
|
|
178
|
+
beside it, so resolving one and not the other would answer one question from
|
|
179
|
+
two different homes: counts of workers and notes from the overridden state
|
|
180
|
+
directory, counts of in-flight and queued work from the home's own backlog.
|
|
181
|
+
A spliced answer is worse than a wrong one, because nothing about it looks
|
|
182
|
+
wrong.
|
|
183
|
+
"""
|
|
184
|
+
override = os.environ.get("FM_DATA_OVERRIDE")
|
|
185
|
+
if override:
|
|
186
|
+
return override
|
|
187
|
+
return os.path.join(home, "data")
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def config_dir(home):
|
|
191
|
+
"""Return the configuration directory, honouring the repo-wide override."""
|
|
192
|
+
override = os.environ.get("FM_CONFIG_OVERRIDE")
|
|
193
|
+
if override:
|
|
194
|
+
return override
|
|
195
|
+
return os.path.join(home, "config")
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def _read_config(home, name):
|
|
199
|
+
path = os.path.join(config_dir(home), name)
|
|
200
|
+
try:
|
|
201
|
+
with open(path, encoding="utf-8") as handle:
|
|
202
|
+
return handle.read()
|
|
203
|
+
except FileNotFoundError:
|
|
204
|
+
return None
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def read_setting(home, name, env=None):
|
|
208
|
+
"""Return a one-line setting from the environment or this home's config, else None.
|
|
209
|
+
|
|
210
|
+
The values this feature needs, an AWS profile and a region and a model id,
|
|
211
|
+
name somebody's account and somebody's choices. They belong to the home that
|
|
212
|
+
runs the relay rather than to the repository, so they are read from gitignored
|
|
213
|
+
config/ with an environment override and never carry a tracked default.
|
|
214
|
+
"""
|
|
215
|
+
if env:
|
|
216
|
+
value = (os.environ.get(env) or "").strip()
|
|
217
|
+
if value:
|
|
218
|
+
return value
|
|
219
|
+
raw = _read_config(home, name)
|
|
220
|
+
if raw is None:
|
|
221
|
+
return None
|
|
222
|
+
for line in raw.splitlines():
|
|
223
|
+
text = line.split("#", 1)[0].strip()
|
|
224
|
+
if text:
|
|
225
|
+
return text
|
|
226
|
+
return None
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def require_setting(home, name, env, what):
|
|
230
|
+
"""Return a setting, or refuse naming the file to write and the variable to set."""
|
|
231
|
+
value = read_setting(home, name, env)
|
|
232
|
+
if value is None:
|
|
233
|
+
raise RecordError(
|
|
234
|
+
"no {} is configured: write one line into {} or set {}".format(
|
|
235
|
+
what, os.path.join(config_dir(home), name), env))
|
|
236
|
+
return value
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
def read_scope(home):
|
|
240
|
+
"""Return the configured read scope, defaulting to the narrowest one."""
|
|
241
|
+
raw = _read_config(home, "voice-read-scope")
|
|
242
|
+
if raw is None:
|
|
243
|
+
return SCOPE_DEFAULT
|
|
244
|
+
value = raw.strip()
|
|
245
|
+
if not value:
|
|
246
|
+
return SCOPE_DEFAULT
|
|
247
|
+
if value not in SCOPES:
|
|
248
|
+
raise RecordError(
|
|
249
|
+
"config/voice-read-scope says {!r}; it must be one of {}".format(
|
|
250
|
+
value, " or ".join(SCOPES)))
|
|
251
|
+
return value
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def deny_list(home):
|
|
255
|
+
"""Return the deny substrings; an absent file means an empty list."""
|
|
256
|
+
raw = _read_config(home, "voice-read-deny")
|
|
257
|
+
if raw is None:
|
|
258
|
+
return []
|
|
259
|
+
out = []
|
|
260
|
+
for line in raw.splitlines():
|
|
261
|
+
text = line.split("#", 1)[0].strip()
|
|
262
|
+
if text:
|
|
263
|
+
out.append(text.lower())
|
|
264
|
+
return out
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
def _denied(denies, *fields):
|
|
268
|
+
haystack = " ".join(f for f in fields if f).lower()
|
|
269
|
+
return any(needle in haystack for needle in denies)
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
def _parse_backlog(path):
|
|
273
|
+
"""Return (section, item) pairs for every task line in the backlog."""
|
|
274
|
+
items = []
|
|
275
|
+
section = ""
|
|
276
|
+
try:
|
|
277
|
+
with open(path, encoding="utf-8") as handle:
|
|
278
|
+
lines = handle.read().splitlines()
|
|
279
|
+
except FileNotFoundError:
|
|
280
|
+
return items
|
|
281
|
+
for line in lines:
|
|
282
|
+
if line.startswith("## "):
|
|
283
|
+
section = line[3:].strip().lower()
|
|
284
|
+
continue
|
|
285
|
+
if section not in READ_SECTIONS:
|
|
286
|
+
continue
|
|
287
|
+
match = ITEM.match(line)
|
|
288
|
+
if not match:
|
|
289
|
+
continue
|
|
290
|
+
rest = match.group("rest")
|
|
291
|
+
tags = {m.group("key"): m.group("value") for m in TAG.finditer(rest)}
|
|
292
|
+
title = re.sub(r"\s+", " ", DATE_TAG.sub("", TAG.sub("", rest))).strip()
|
|
293
|
+
items.append({
|
|
294
|
+
"section": section,
|
|
295
|
+
"id": match.group("id"),
|
|
296
|
+
"title": title,
|
|
297
|
+
"done": match.group("done") == "x",
|
|
298
|
+
"tags": tags,
|
|
299
|
+
})
|
|
300
|
+
return items
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
def _last_event(state_dir, task_id):
|
|
304
|
+
"""Return (verb, line) from the last status event, or (None, None).
|
|
305
|
+
|
|
306
|
+
bin/fm-classify-lib.sh remains the owner of status-verb normalization.
|
|
307
|
+
This security-bounded projection accepts the prefix before the first ':'
|
|
308
|
+
and the first '[', whichever comes first, only when it is in STATE_VERBS.
|
|
309
|
+
The bracket matters: status metadata sits between the verb and the colon,
|
|
310
|
+
as in "done [token]: shipped it" and "needs-decision [key=api-shape]: which
|
|
311
|
+
shape". A line carrying no colon is not a status line, and any unrecognized
|
|
312
|
+
prefix is reported as a note rather than spoken aloud as a state.
|
|
313
|
+
|
|
314
|
+
Only the tail of the log is read; see STATUS_TAIL_BYTES.
|
|
315
|
+
"""
|
|
316
|
+
path = os.path.join(state_dir, task_id + ".status")
|
|
317
|
+
try:
|
|
318
|
+
with open(path, "rb") as handle:
|
|
319
|
+
handle.seek(0, os.SEEK_END)
|
|
320
|
+
size = handle.tell()
|
|
321
|
+
handle.seek(max(0, size - STATUS_TAIL_BYTES))
|
|
322
|
+
window = handle.read()
|
|
323
|
+
except OSError:
|
|
324
|
+
return None, None
|
|
325
|
+
lines = [text.strip() for text in
|
|
326
|
+
window.decode("utf-8", errors="replace").splitlines() if text.strip()]
|
|
327
|
+
if not lines:
|
|
328
|
+
return None, None
|
|
329
|
+
line = lines[-1]
|
|
330
|
+
verb = NOTE_VERB
|
|
331
|
+
if ":" in line:
|
|
332
|
+
verb = line.split(":", 1)[0].split("[", 1)[0].strip().lower()
|
|
333
|
+
if verb not in STATE_VERBS:
|
|
334
|
+
verb = NOTE_VERB
|
|
335
|
+
return verb, line
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
def _workers(state_dir):
|
|
339
|
+
"""Return one record per task with runtime metadata in this home."""
|
|
340
|
+
out = []
|
|
341
|
+
try:
|
|
342
|
+
names = sorted(n for n in os.listdir(state_dir) if n.endswith(".meta"))
|
|
343
|
+
except OSError:
|
|
344
|
+
return out
|
|
345
|
+
for name in names:
|
|
346
|
+
task_id = name[: -len(".meta")]
|
|
347
|
+
meta = {}
|
|
348
|
+
try:
|
|
349
|
+
with open(os.path.join(state_dir, name), encoding="utf-8") as handle:
|
|
350
|
+
for line in handle:
|
|
351
|
+
if "=" in line:
|
|
352
|
+
key, value = line.rstrip("\n").split("=", 1)
|
|
353
|
+
meta[key] = value
|
|
354
|
+
except OSError:
|
|
355
|
+
continue
|
|
356
|
+
verb, line = _last_event(state_dir, task_id)
|
|
357
|
+
out.append({
|
|
358
|
+
"id": task_id,
|
|
359
|
+
"kind": meta.get("kind", ""),
|
|
360
|
+
"mode": meta.get("mode", ""),
|
|
361
|
+
"pr": meta.get("pr", ""),
|
|
362
|
+
"verb": verb or "no events yet",
|
|
363
|
+
"line": line or "",
|
|
364
|
+
})
|
|
365
|
+
return out
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
def fleet_status(home=None, scope=None):
|
|
369
|
+
"""Return the status answer the voice agent is allowed to give."""
|
|
370
|
+
home = home or default_home()
|
|
371
|
+
scope = scope or read_scope(home)
|
|
372
|
+
if scope not in SCOPES:
|
|
373
|
+
raise RecordError("unknown read scope: {!r}".format(scope))
|
|
374
|
+
denies = deny_list(home)
|
|
375
|
+
|
|
376
|
+
state = state_dir(home)
|
|
377
|
+
workers = _workers(state)
|
|
378
|
+
items = _parse_backlog(os.path.join(data_dir(home), "backlog.md"))
|
|
379
|
+
|
|
380
|
+
open_items = [i for i in items if not i["done"]]
|
|
381
|
+
in_flight = [i for i in open_items if i["section"] == "in flight"]
|
|
382
|
+
queued = [i for i in open_items if i["section"] == "queued"]
|
|
383
|
+
# "What is waiting on me" is the union of decisions filed for the captain
|
|
384
|
+
# and anything explicitly held for them. The two overlap but neither
|
|
385
|
+
# contains the other, because a decision can be filed before it is held.
|
|
386
|
+
held_for_captain = [
|
|
387
|
+
i for i in open_items
|
|
388
|
+
if i["tags"].get("hold-kind") == "captain"
|
|
389
|
+
or i["tags"].get("kind") == "captain"
|
|
390
|
+
]
|
|
391
|
+
# OPEN work only. _workers lists every state/*.meta in the home, and a task
|
|
392
|
+
# keeps its meta after it is marked done until teardown removes it, so taking
|
|
393
|
+
# every worker with a pull request would count and name finished tasks. That
|
|
394
|
+
# breaks the promise at the top of this file twice over: it reads finished
|
|
395
|
+
# work, and the deny decision below cannot reach those items, because their
|
|
396
|
+
# ids have no open item to supply a title, so a captain substring matching a
|
|
397
|
+
# title would silently fail for exactly them. Losing the count of a pull
|
|
398
|
+
# request on a task already marked done is the accepted cost.
|
|
399
|
+
open_ids = {i["id"] for i in open_items}
|
|
400
|
+
with_pr = [w for w in workers if w["pr"] and w["id"] in open_ids]
|
|
401
|
+
|
|
402
|
+
inbox = os.path.join(state, "inbox")
|
|
403
|
+
try:
|
|
404
|
+
waiting = len([n for n in os.listdir(inbox) if n.endswith(".note")])
|
|
405
|
+
except OSError:
|
|
406
|
+
waiting = 0
|
|
407
|
+
|
|
408
|
+
states = {}
|
|
409
|
+
for worker in workers:
|
|
410
|
+
states[worker["verb"]] = states.get(worker["verb"], 0) + 1
|
|
411
|
+
|
|
412
|
+
answer = {
|
|
413
|
+
"scope": scope,
|
|
414
|
+
"basis": BASIS,
|
|
415
|
+
"workers_on_deck": len(workers),
|
|
416
|
+
"worker_states": states,
|
|
417
|
+
"in_flight": len(in_flight),
|
|
418
|
+
"queued": len(queued),
|
|
419
|
+
"awaiting_captain": len(held_for_captain),
|
|
420
|
+
"open_pull_requests": len(with_pr),
|
|
421
|
+
"captain_notes_waiting": waiting,
|
|
422
|
+
}
|
|
423
|
+
if scope == SCOPE_COUNTS:
|
|
424
|
+
answer["detail"] = (
|
|
425
|
+
"Identifiers, titles and pull request links are withheld at this "
|
|
426
|
+
"read scope. Say that the detail is not available by voice rather "
|
|
427
|
+
"than guessing at it.")
|
|
428
|
+
return answer
|
|
429
|
+
|
|
430
|
+
by_id = {w["id"]: w for w in workers}
|
|
431
|
+
|
|
432
|
+
# ONE deny decision per item, taken over everything known about that item
|
|
433
|
+
# before any list is built, and then shared by every list it could appear
|
|
434
|
+
# in. The lists overlap by design: a task can be in flight, waiting on the
|
|
435
|
+
# captain and carrying a pull request at once. Deciding per list, from the
|
|
436
|
+
# fields that list happens to use, would withhold an item from one list and
|
|
437
|
+
# name it in another, which is not a narrower answer but a leak with a
|
|
438
|
+
# reassuring count beside it. It also makes the count what it says it is,
|
|
439
|
+
# distinct items rather than refusals.
|
|
440
|
+
#
|
|
441
|
+
# The fields come from every OPEN item, not only the ones a list iterates. A
|
|
442
|
+
# queued item that is not held for the captain still reaches the answer
|
|
443
|
+
# through its pull request link, and assembling its fields only where a list
|
|
444
|
+
# walks past it is how a title match gets missed on exactly that item. What
|
|
445
|
+
# is COUNTED is narrower: an item that no list could have named is not
|
|
446
|
+
# something the captain is having withheld.
|
|
447
|
+
known = {}
|
|
448
|
+
for item in open_items:
|
|
449
|
+
known.setdefault(item["id"], item)
|
|
450
|
+
nameable = ({i["id"] for i in in_flight} | {i["id"] for i in held_for_captain}
|
|
451
|
+
| {w["id"] for w in with_pr})
|
|
452
|
+
|
|
453
|
+
withheld_ids = set()
|
|
454
|
+
for item_id in nameable:
|
|
455
|
+
item = known.get(item_id)
|
|
456
|
+
worker = by_id.get(item_id)
|
|
457
|
+
fields = [item_id]
|
|
458
|
+
if item is not None:
|
|
459
|
+
fields.append(item["title"])
|
|
460
|
+
fields.extend(item["tags"].values())
|
|
461
|
+
if worker is not None:
|
|
462
|
+
fields.append(worker["pr"])
|
|
463
|
+
if _denied(denies, *fields):
|
|
464
|
+
withheld_ids.add(item_id)
|
|
465
|
+
|
|
466
|
+
def keep(item_id):
|
|
467
|
+
return item_id not in withheld_ids
|
|
468
|
+
|
|
469
|
+
detail_in_flight = []
|
|
470
|
+
for item in in_flight:
|
|
471
|
+
if not keep(item["id"]):
|
|
472
|
+
continue
|
|
473
|
+
worker = by_id.get(item["id"])
|
|
474
|
+
detail_in_flight.append({
|
|
475
|
+
"id": item["id"],
|
|
476
|
+
"title": item["title"],
|
|
477
|
+
# The state word only, never the raw event line. The agent speaks to
|
|
478
|
+
# the captain and must not read internal record text aloud.
|
|
479
|
+
"state": worker["verb"] if worker else "not started",
|
|
480
|
+
})
|
|
481
|
+
|
|
482
|
+
detail_captain = []
|
|
483
|
+
for item in held_for_captain:
|
|
484
|
+
if not keep(item["id"]):
|
|
485
|
+
continue
|
|
486
|
+
detail_captain.append({"id": item["id"], "title": item["title"]})
|
|
487
|
+
|
|
488
|
+
detail_prs = []
|
|
489
|
+
for worker in with_pr:
|
|
490
|
+
if not keep(worker["id"]):
|
|
491
|
+
continue
|
|
492
|
+
detail_prs.append({"id": worker["id"], "url": worker["pr"]})
|
|
493
|
+
|
|
494
|
+
def capped(rows, key):
|
|
495
|
+
answer[key] = rows[:DETAIL_LIMIT]
|
|
496
|
+
if len(rows) > DETAIL_LIMIT:
|
|
497
|
+
answer[key + "_not_listed"] = len(rows) - DETAIL_LIMIT
|
|
498
|
+
|
|
499
|
+
capped(detail_in_flight, "in_flight_detail")
|
|
500
|
+
capped(detail_captain, "awaiting_captain_detail")
|
|
501
|
+
capped(detail_prs, "pull_request_detail")
|
|
502
|
+
answer["withheld_as_confidential"] = len(withheld_ids)
|
|
503
|
+
answer["detail"] = (
|
|
504
|
+
"The lists name at most {} items each; the counts above are the whole "
|
|
505
|
+
"picture. Give the captain the counts and a couple of names, not every "
|
|
506
|
+
"row.".format(DETAIL_LIMIT))
|
|
507
|
+
return answer
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
def queue_request(text, home=None, root=None):
|
|
511
|
+
"""Hand real work to firstmate through bin/fm-inbox.sh note."""
|
|
512
|
+
home = home or default_home()
|
|
513
|
+
root = root or os.path.dirname(os.path.abspath(__file__))
|
|
514
|
+
body = (text or "").strip()
|
|
515
|
+
if not body:
|
|
516
|
+
raise RecordError("refusing to queue an empty request")
|
|
517
|
+
inbox = os.path.join(root, "fm-inbox.sh")
|
|
518
|
+
if not os.access(inbox, os.X_OK):
|
|
519
|
+
raise RecordError("cannot run {}".format(inbox))
|
|
520
|
+
env = dict(os.environ, FM_HOME=home)
|
|
521
|
+
done = subprocess.run(
|
|
522
|
+
[inbox, "note", body],
|
|
523
|
+
# The relay's stdin is the captain's audio when this runs under
|
|
524
|
+
# --serve, and fm-inbox.sh reads a body from stdin for an argument of
|
|
525
|
+
# "-", so no child of the relay is given that stream to consume.
|
|
526
|
+
stdin=subprocess.DEVNULL,
|
|
527
|
+
env=env, capture_output=True, text=True, timeout=30, check=False)
|
|
528
|
+
if done.returncode != 0:
|
|
529
|
+
raise RecordError("fm-inbox.sh note failed: {}".format(
|
|
530
|
+
(done.stderr or done.stdout).strip()))
|
|
531
|
+
note_id = ""
|
|
532
|
+
for line in done.stdout.splitlines():
|
|
533
|
+
if line.startswith("queued "):
|
|
534
|
+
note_id = line.split(None, 1)[1].strip()
|
|
535
|
+
break
|
|
536
|
+
return {
|
|
537
|
+
"queued": True,
|
|
538
|
+
"note_id": note_id,
|
|
539
|
+
"queued_text": body,
|
|
540
|
+
"handover": "Firstmate now owns this request and will pick it up at "
|
|
541
|
+
"its next check. You did not do the work yourself.",
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
|
|
545
|
+
def main(argv):
|
|
546
|
+
parser = argparse.ArgumentParser(
|
|
547
|
+
prog="fm_voice_records.py", description=__doc__.splitlines()[0],
|
|
548
|
+
formatter_class=argparse.RawDescriptionHelpFormatter)
|
|
549
|
+
sub = parser.add_subparsers(dest="command", required=True)
|
|
550
|
+
|
|
551
|
+
status = sub.add_parser("status", help="print the allowed status answer")
|
|
552
|
+
status.add_argument("--home")
|
|
553
|
+
status.add_argument("--scope", choices=SCOPES)
|
|
554
|
+
|
|
555
|
+
queue = sub.add_parser("queue", help="hand a request to firstmate")
|
|
556
|
+
queue.add_argument("text", nargs="+")
|
|
557
|
+
queue.add_argument("--home")
|
|
558
|
+
|
|
559
|
+
args = parser.parse_args(argv)
|
|
560
|
+
try:
|
|
561
|
+
if args.command == "status":
|
|
562
|
+
result = fleet_status(home=args.home, scope=args.scope)
|
|
563
|
+
else:
|
|
564
|
+
result = queue_request(" ".join(args.text), home=args.home)
|
|
565
|
+
except RecordError as exc:
|
|
566
|
+
sys.stderr.write("fm_voice_records: {}\n".format(exc))
|
|
567
|
+
return 2
|
|
568
|
+
json.dump(result, sys.stdout, indent=2, sort_keys=True)
|
|
569
|
+
sys.stdout.write("\n")
|
|
570
|
+
return 0
|
|
571
|
+
|
|
572
|
+
|
|
573
|
+
if __name__ == "__main__":
|
|
574
|
+
sys.exit(main(sys.argv[1:]))
|