@zerwiz/ymir 0.1.16 → 0.1.18

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.
Files changed (171) hide show
  1. package/.agents/config/app-repos.yaml +38 -0
  2. package/.claude/settings.json +31 -0
  3. package/.codex/hooks.json +43 -0
  4. package/.cursor/hooks.json +33 -0
  5. package/.pi/extensions/README.md +39 -0
  6. package/.pi/extensions/gna-pi-watch.ts +15 -0
  7. package/.pi/extensions/lib/ro-assistant-layout.ts +96 -0
  8. package/.pi/extensions/lib/ro-operational-user-layout.ts +145 -0
  9. package/.pi/extensions/lib/ro-visibility.ts +99 -0
  10. package/.pi/extensions/lib/ro-working-ship.ts +243 -0
  11. package/.pi/extensions/lib/rodd-operational-input.ts +62 -0
  12. package/.pi/extensions/lib/skuld-branch-dispatch.ts +252 -0
  13. package/.pi/extensions/lib/skuld-branch-model-picker.ts +77 -0
  14. package/.pi/extensions/lib/vordr-sessionstart-supervisor.mjs +48 -0
  15. package/.pi/extensions/ro.ts +11 -0
  16. package/.pi/extensions/skuld-branch-supervision.ts +11 -0
  17. package/.pi/extensions/syn-turnend-guard.ts +11 -0
  18. package/.pi/mcp.json +16 -0
  19. package/.pi/mcp.json.example +11 -0
  20. package/.pi/npm/.gitignore +2 -0
  21. package/.pi/settings.json +8 -0
  22. package/.pi/shared/extensions/gna-pi-watch.ts +750 -0
  23. package/.pi/shared/extensions/herdr-agent-state.ts +257 -0
  24. package/.pi/shared/extensions/open-editor.ts +509 -0
  25. package/.pi/shared/extensions/ro.ts +504 -0
  26. package/.pi/shared/extensions/skuld-branch-supervision.ts +1535 -0
  27. package/.pi/shared/extensions/syn-turnend-guard.ts +683 -0
  28. package/.pi/shared/extensions/todo.ts +133 -0
  29. package/.pi/shared/extensions/ymir-subagents.ts +287 -0
  30. package/.pi/shared/extensions/ymir-well.ts +130 -0
  31. package/CHANGELOG.md +23 -0
  32. package/assets/Ymir.md +4654 -0
  33. package/assets/healer.html +717 -0
  34. package/assets/icon-family/family-sheet.png +0 -0
  35. package/assets/icon-family/hlidskjalf.svg +1 -0
  36. package/assets/icon-family/sessrumnir.svg +1 -0
  37. package/assets/icon-family/smidja.svg +1 -0
  38. package/assets/icon-family/ymir.svg +1 -0
  39. package/assets/mimirswell.html +880 -0
  40. package/assets/mock/README.md +16 -0
  41. package/assets/mock/feeds.ts +175 -0
  42. package/assets/mock/mock.ts +408 -0
  43. package/assets/reference/docs/agent-control.md +122 -0
  44. package/assets/reference/docs/apodex/Appdex_as_Orchestrator_Planner_Reviewer_Assessment.md +176 -0
  45. package/assets/reference/docs/apodex/Final Report(1).md +198 -0
  46. package/assets/reference/docs/apodex/Final Report(2).md +54 -0
  47. package/assets/reference/docs/apodex/Final Report(3).md +40 -0
  48. package/assets/reference/docs/apodex/Final Report(4).md +234 -0
  49. package/assets/reference/docs/apodex/Final Report(5).md +13 -0
  50. package/assets/reference/docs/apodex/Final Report.md +82 -0
  51. package/assets/reference/docs/architecture.md +392 -0
  52. package/assets/reference/docs/arm-pretool-check.md +247 -0
  53. package/assets/reference/docs/calm-mode-feasibility.md +541 -0
  54. package/assets/reference/docs/calm.md +59 -0
  55. package/assets/reference/docs/captain-hold-lifecycle.md +96 -0
  56. package/assets/reference/docs/cd-guard.md +165 -0
  57. package/assets/reference/docs/cmux-backend.md +133 -0
  58. package/assets/reference/docs/codex-app-backend.md +57 -0
  59. package/assets/reference/docs/configuration.md +924 -0
  60. package/assets/reference/docs/documentation-audiences.json +468 -0
  61. package/assets/reference/docs/documentation-audiences.md +28 -0
  62. package/assets/reference/docs/examples/crew-dispatch.json +26 -0
  63. package/assets/reference/docs/examples/process-event-extension/file-signal.mjs +96 -0
  64. package/assets/reference/docs/examples/process-event-extension/firstmate-extension.json +15 -0
  65. package/assets/reference/docs/examples/watched-tools.json +24 -0
  66. package/assets/reference/docs/examples/wedge-alarm +22 -0
  67. package/assets/reference/docs/extension-bindings.md +237 -0
  68. package/assets/reference/docs/fm-test-isolation-proof.json +37 -0
  69. package/assets/reference/docs/fm-test-isolation-proof.md +149 -0
  70. package/assets/reference/docs/fm-test-portable-shards.md +118 -0
  71. package/assets/reference/docs/gitlab-merge-watch.md +275 -0
  72. package/assets/reference/docs/herdr-backend.md +346 -0
  73. package/assets/reference/docs/orca-backend.md +84 -0
  74. package/assets/reference/docs/pi-supervision-branch-poster.svg +125 -0
  75. package/assets/reference/docs/pi-supervision-branch.md +96 -0
  76. package/assets/reference/docs/plans/agentic-engineering-workflow.md +395 -0
  77. package/assets/reference/docs/plans/agentic-factory-implementation-plan.md +615 -0
  78. package/assets/reference/docs/plans/command-factory-enhancement-plan.md +420 -0
  79. package/assets/reference/docs/plans/phase-1-layer3-program-design.md +134 -0
  80. package/assets/reference/docs/plans/phase-2-vertical-slices.md +100 -0
  81. package/assets/reference/docs/plans/phase-3-measurable-goals.md +106 -0
  82. package/assets/reference/docs/plans/phase-4-context-budget.md +106 -0
  83. package/assets/reference/docs/plans/phase-5-pre-mortem-confidence.md +100 -0
  84. package/assets/reference/docs/plans/phase-6-incident-to-agent.md +109 -0
  85. package/assets/reference/docs/remote-secondmates.md +268 -0
  86. package/assets/reference/docs/scripts.md +146 -0
  87. package/assets/reference/docs/sessionstart-nudge.md +115 -0
  88. package/assets/reference/docs/subagent-guard.md +383 -0
  89. package/assets/reference/docs/supervision-protocols/claude.md +27 -0
  90. package/assets/reference/docs/supervision-protocols/codex.md +16 -0
  91. package/assets/reference/docs/supervision-protocols/cursor.md +31 -0
  92. package/assets/reference/docs/supervision-protocols/grok.md +39 -0
  93. package/assets/reference/docs/supervision-protocols/opencode.md +17 -0
  94. package/assets/reference/docs/supervision-protocols/pi.md +33 -0
  95. package/assets/reference/docs/supervision-protocols/unknown.md +13 -0
  96. package/assets/reference/docs/tmux-backend.md +115 -0
  97. package/assets/reference/docs/trace-context.md +117 -0
  98. package/assets/reference/docs/turnend-guard.md +170 -0
  99. package/assets/reference/docs/verification/dispatch-auth.md +204 -0
  100. package/assets/reference/docs/verification/muse.md +221 -0
  101. package/assets/reference/docs/verification/process-event-sources.md +208 -0
  102. package/assets/reference/docs/verification/public-followup.md +119 -0
  103. package/assets/reference/docs/verification/runtime-backends.md +1022 -0
  104. package/assets/reference/docs/verification/stow-memory.md +53 -0
  105. package/assets/reference/docs/verification/supervision.md +534 -0
  106. package/assets/reference/docs/verification/trace-context.md +31 -0
  107. package/assets/reference/docs/voice-relay.md +295 -0
  108. package/assets/reference/docs/watcher-continuity.md +119 -0
  109. package/assets/reference/docs/wedge-alarm.md +39 -0
  110. package/assets/reference/docs/zellij-backend.md +114 -0
  111. package/assets/reference/index.html +1172 -0
  112. package/assets/reference/skills/afk/SKILL.md +241 -0
  113. package/assets/reference/skills/ahoy/SKILL.md +56 -0
  114. package/assets/reference/skills/ask-user-authority/SKILL.md +56 -0
  115. package/assets/reference/skills/bearings/SKILL.md +161 -0
  116. package/assets/reference/skills/bearings/assets/board-template.html +731 -0
  117. package/assets/reference/skills/bootstrap-diagnostics/SKILL.md +68 -0
  118. package/assets/reference/skills/captain-hold-lifecycle/SKILL.md +54 -0
  119. package/assets/reference/skills/decision-hold-lifecycle/SKILL.md +15 -0
  120. package/assets/reference/skills/diagnostic-reasoning/SKILL.md +53 -0
  121. package/assets/reference/skills/firstmate-codexapp/SKILL.md +110 -0
  122. package/assets/reference/skills/firstmate-codexapp/agents/openai.yaml +4 -0
  123. package/assets/reference/skills/firstmate-coding-guidelines/SKILL.md +127 -0
  124. package/assets/reference/skills/firstmate-orca/SKILL.md +92 -0
  125. package/assets/reference/skills/fmx-respond/SKILL.md +283 -0
  126. package/assets/reference/skills/harness-adapters/SKILL.md +95 -0
  127. package/assets/reference/skills/harness-adapters/references/common/control-and-recovery.md +37 -0
  128. package/assets/reference/skills/harness-adapters/references/common/dispatch.md +32 -0
  129. package/assets/reference/skills/harness-adapters/references/common/model-and-effort.md +42 -0
  130. package/assets/reference/skills/harness-adapters/references/common/primary-hooks.md +40 -0
  131. package/assets/reference/skills/harness-adapters/references/harness/claude.md +55 -0
  132. package/assets/reference/skills/harness-adapters/references/harness/codex.md +43 -0
  133. package/assets/reference/skills/harness-adapters/references/harness/cursor.md +75 -0
  134. package/assets/reference/skills/harness-adapters/references/harness/grok.md +69 -0
  135. package/assets/reference/skills/harness-adapters/references/harness/kimi.md +51 -0
  136. package/assets/reference/skills/harness-adapters/references/harness/muse.md +70 -0
  137. package/assets/reference/skills/harness-adapters/references/harness/opencode.md +42 -0
  138. package/assets/reference/skills/harness-adapters/references/harness/pi.md +56 -0
  139. package/assets/reference/skills/process-event-sources/SKILL.md +137 -0
  140. package/assets/reference/skills/project-management/SKILL.md +92 -0
  141. package/assets/reference/skills/quota-array-dispatch/SKILL.md +131 -0
  142. package/assets/reference/skills/secondmate-provisioning/SKILL.md +254 -0
  143. package/assets/reference/skills/stow/SKILL.md +309 -0
  144. package/assets/reference/skills/stuck-crewmate-recovery/SKILL.md +54 -0
  145. package/assets/reference/skills/updatefirstmate/SKILL.md +64 -0
  146. package/assets/skills/README.md +5 -0
  147. package/assets/yggdrasil.html +649 -0
  148. package/assets/ymir-banner-01.png +0 -0
  149. package/assets/ymir-banner-02.png +0 -0
  150. package/assets/ymir-banner-03.png +0 -0
  151. package/assets/ymir-banner-04.png +0 -0
  152. package/assets/ymir-banner-05.png +0 -0
  153. package/assets/ymir-banner-06.png +0 -0
  154. package/assets/ymir-emblem-darksteel.svg +63 -0
  155. package/assets/ymir-emblem-forged.svg +55 -0
  156. package/assets/ymir-emblem-slate.svg +55 -0
  157. package/assets/ymir-mark-algiz-anvil.svg +9 -0
  158. package/assets/ymir-stave.svg +53 -0
  159. package/assets/ymir.html +563 -0
  160. package/bin/ymir-install.sh +6 -1
  161. package/data/learnings.md +33 -0
  162. package/data/local-models.md +34 -0
  163. package/data/operator.md +15 -0
  164. package/data/projects.md +28 -0
  165. package/data/realm.md +1 -0
  166. package/deploy/Containerfile +27 -0
  167. package/deploy/README.md +104 -0
  168. package/deploy/compose/compose.yaml +45 -0
  169. package/deploy/env.example +30 -0
  170. package/deploy/quadlet/ymir.container +57 -0
  171. package/package.json +10 -8
@@ -0,0 +1,204 @@
1
+ # Dispatch authentication verification
2
+
3
+ Audience: maintainer verification.
4
+
5
+ This record supports the dispatch judgment rules in `.agents/skills/quota-array-dispatch/SKILL.md` and the bounded vendor probe in `bin/fm-vendor-auth-probe.sh`.
6
+ It records only facts that must be re-established when a producer or vendor version changes.
7
+ Task chronology, incident transcripts, and credential metadata stay in private reports or PR evidence.
8
+
9
+ Firstmate resolves a candidate's provider family, credential surface, and applicable quota by reading the evidence below and reasoning in the open.
10
+ No script maps a model to a provider, a provider to a credential store, or a name prefix to a family, so the facts here are what that reasoning rests on.
11
+ Credential paths below are shown with the home directory replaced by `<home>`.
12
+
13
+ ## Quota granularity the judgment depends on
14
+
15
+ Verified 2026-07-30 against quota-axi 0.1.16 for the provider and model-scope relationships below.
16
+ That release's captured default output included `quotaSemantics.description`; the current default TOON and JSON fallback field placement are verified against 0.1.29 in the next section.
17
+ Current dispatch reads the TOON scope and `limitedBy` fields; the JSON fallback's corresponding `scope` and `boundedBy` fields preserve the same provider/model applicability without relying on the `--full`-only description.
18
+
19
+ ```json
20
+ {
21
+ "provider": "codex",
22
+ "state": { "status": "fresh", "stale": false },
23
+ "quotaSemantics": {
24
+ "status": "known",
25
+ "description": "Codex base account windows bound every model. Named model windows add bounds for that model; code-review windows describe a separate workload and are not included in model availability.",
26
+ "effectiveAvailability": [
27
+ { "scope": "all_models", "status": "known", "effectivePercentRemaining": 64, "boundedBy": ["weekly"] },
28
+ { "scope": "model:codex_bengalfox", "status": "known", "effectivePercentRemaining": 64, "boundedBy": ["weekly", "model:codex_bengalfox:7d"] }
29
+ ]
30
+ }
31
+ }
32
+ ```
33
+
34
+ Three properties follow and are load-bearing for dispatch:
35
+
36
+ - An `all_models` (or `all_products`) scope is real evidence for every model in that provider family, including a model with no window of its own.
37
+ - A `model:`-scoped entry is an additional bound for that one model. `model:codex_bengalfox` is the GPT-5.3-Codex-Spark window and bounds nothing else.
38
+ - A named-model window can be tighter than the account bound, so it must not be read across models. In the same snapshot Claude reported `all_models` with `effectivePercentRemaining` 10 while `model:fable` reported 4, limited by the `model:fable` window itself. A non-Fable Claude model reads 10, not 4.
39
+
40
+ `quotaSemantics.status` is `unknown` with no `effectiveAvailability` entries at all for providers whose vendor exposes no window (observed for `cursor` and `copilot`).
41
+ `state.authStatus` is present only for some providers (observed for `grok` alone), so its absence is missing evidence, not a credential fault.
42
+
43
+ ## Completion-runway and selection shape the judgment depends on
44
+
45
+ Verified 2026-08-18 against quota-axi 0.1.29 schema 5, captured from an isolated `quota-axi@0.1.29` install.
46
+ The default TOON exposed these table headers, with row counts normalized to `N`:
47
+
48
+ ```text
49
+ quota[N]{provider,scope,effectivePercentRemaining,spendPriority,runway,confidence,limitedBy,resetsAt}:
50
+ exhaustion[N]{provider,scope,usableRunwaySeconds,projectedExhaustedAt,limitingWindowId}:
51
+ attention[N]{provider,scope,kind,detail,remedy}:
52
+ ```
53
+
54
+ `exhaustion[]` and `attention[]` are sparse, so an empty table is rendered with count zero and no row fields.
55
+ The command below records the JSON fallback shape without persisting account-specific quota values:
56
+
57
+ ```sh
58
+ quota-axi --json | jq '{schemaVersion, effectiveAvailabilityFields: ([.providers[]?.quotaSemantics.effectiveAvailability[]? | keys] | unique), runwayFields: ([.providers[]?.quotaSemantics.effectiveAvailability[]?.runway? | select(type == "object") | keys] | unique), selectionFields: ([.providers[]?.quotaSemantics.effectiveAvailability[]?.selection? | select(type == "object") | keys] | unique), paceFields: ([.providers[]?.quotaSemantics.effectiveAvailability[]?.pace? | select(type == "object") | keys] | unique), windowPaceFields: ([.providers[]?.windows[]?.pace? | select(type == "object") | keys] | unique)}'
59
+ ```
60
+
61
+ ```json
62
+ {
63
+ "schemaVersion": 5,
64
+ "effectiveAvailabilityFields": [
65
+ [
66
+ "boundedBy",
67
+ "effectivePercentRemaining",
68
+ "limitingWindowIds",
69
+ "pace",
70
+ "runway",
71
+ "scope",
72
+ "selection",
73
+ "status"
74
+ ]
75
+ ],
76
+ "runwayFields": [
77
+ [
78
+ "projectionConfidence",
79
+ "status"
80
+ ]
81
+ ],
82
+ "selectionFields": [
83
+ [
84
+ "spendPriority",
85
+ "status"
86
+ ]
87
+ ],
88
+ "paceFields": [
89
+ [
90
+ "status",
91
+ "worstReservePercentPoints",
92
+ "worstReserveWindowId"
93
+ ]
94
+ ],
95
+ "windowPaceFields": [
96
+ [
97
+ "burnMultiple",
98
+ "reservePercentPoints",
99
+ "status"
100
+ ]
101
+ ]
102
+ }
103
+ ```
104
+
105
+ This live snapshot was all `through_reset`, so finite-runway fields were omitted.
106
+ `usableRunwaySeconds`, `projectedExhaustedAt`, and `limitingWindowId` remain in default `--json` when `runway.status` is `projected_exhaustion` or `exhausted_now`.
107
+ `selection.unmeasurableWindowIds`, scope `aheadWindowIds`/`unknownWindowIds`, and window `pace.reason` likewise remain in default `--json` when they apply.
108
+ `quotaSemantics.description`, `behindWindowIds`, `onPaceWindowIds`, and per-window cycle-progress internals are `--full` only.
109
+ There is no `projectionBasis` field; its absence means `cycle_average`.
110
+ `runway` and `selection` are nested under each effective-availability scope, so the same provider/model applicability rules govern headroom, runway, and `spendPriority`.
111
+ Projection confidence is not present on every known runway, so selection must preserve that absence as uncertainty rather than fabricate it.
112
+ The older-schema fallback contract is owned by `quota-array-dispatch`; this evidence does not reinterpret an absent runway, pace, or selection field.
113
+
114
+ ## Provider-family counterfactual that this producer schema supports
115
+
116
+ Verified 2026-07-30 on Pi 0.82.0 and quota-axi 0.1.16.
117
+
118
+ ```sh
119
+ pi --list-models terra
120
+ ```
121
+
122
+ ```text
123
+ provider model context max-out thinking images
124
+ openai-codex gpt-5.6-terra 272K 128K yes yes
125
+ ```
126
+
127
+ The Pi catalog is authoritative for Pi model support and reports the provider family in its own column.
128
+ For `harness=pi`, `model=openai-codex/gpt-5.6-terra` the catalog establishes the model is supported and belongs to the `openai-codex` family, and the Codex `all_models` scope above supplies fresh, known 64 effective remaining for every model in that family.
129
+ No Terra-specific window exists in the snapshot, and `quota-axi auth --json` lists no `pi:openai-codex` source.
130
+ Both absences are missing model-level and source-level detail, not contradictory evidence, so this candidate is dispatchable with the model-level uncertainty disclosed.
131
+
132
+ ```sh
133
+ pi --list-models gpt-9.9-nonexistent
134
+ ```
135
+
136
+ ```text
137
+ No models matching "gpt-9.9-nonexistent"
138
+ ```
139
+
140
+ A listing that reaches the account and returns no row is the authoritative negative that does block a candidate.
141
+
142
+ ## Credential sources are independent per provider
143
+
144
+ Verified 2026-07-30 against quota-axi 0.1.16.
145
+
146
+ `quota-axi auth --json` reports each provider's credential sources separately, which is what lets a candidate be scoped to the one surface it actually authenticates through:
147
+
148
+ ```json
149
+ [
150
+ { "provider": "claude", "sources": [
151
+ { "source": "oauth-file", "path": "<home>/.claude/.credentials.json", "status": "missing" },
152
+ { "source": "keychain", "status": "available" } ] },
153
+ { "provider": "codex", "sources": [
154
+ { "source": "auth-json", "path": "<home>/.codex/auth.json", "status": "available" },
155
+ { "source": "cli-rpc", "path": "<path-to>/codex", "status": "available" } ] },
156
+ { "provider": "grok", "sources": [
157
+ { "source": "auth-json", "path": "<home>/.grok/auth.json", "status": "available" },
158
+ { "source": "pi:xai", "status": "available" } ] },
159
+ { "provider": "kimi", "sources": [
160
+ { "source": "pi:kimi-coding", "status": "available" },
161
+ { "source": "kimi-code-cli", "status": "expired", "error": "kimi_code_cli_credential_expired" } ] }
162
+ ]
163
+ ```
164
+
165
+ Observed source statuses are `available`, `expired` (with an `error` slug), and `missing`.
166
+
167
+ - A provider can carry a healthy source beside a missing or expired one, so a provider must not be collapsed to a single status. Claude's `oauth-file` is missing while its keychain source is available, and Kimi's standalone CLI credential is expired while its Pi source is available.
168
+ - A `pi:`-prefixed source exists only where Pi holds its own credential for that family (`pi:xai`, `pi:kimi-coding`). Pi's `openai-codex` family has none, because it authenticates through the Codex store that the `codex` provider already lists. A missing `pi:` source is therefore never evidence against a Pi candidate.
169
+
170
+ Neither this per-source shape nor `state.authStatus` exists before quota-axi 0.1.16.
171
+ `bin/fm-bootstrap.sh` enforces the current compatibility floor through `bin/fm-quota-axi-lib.sh`.
172
+
173
+ Grok also reports `credits.remaining: 0` alongside `percentRemaining: 41` on a healthy account.
174
+ That zero is a prepaid balance, not the subscription window, and is never headroom.
175
+
176
+ ## Standalone Grok discovery probe
177
+
178
+ Verified 2026-07-30 on `grok 0.2.117 (f1c06093089f) [stable]`.
179
+
180
+ ```sh
181
+ grok --version
182
+ grok models # stdin closed, single attempt, hard-bounded
183
+ ```
184
+
185
+ Observed:
186
+
187
+ - `grok models` exits `0` and its first stdout line is `You are logged in with grok.com.` for an authenticated session.
188
+ - With a home directory holding no Grok credential, the first stdout line is `You are not authenticated.`, also with exit status `0`.
189
+ - Because the status is `0` in both cases, the exit status is not a verdict; only the literal first stdout line is examined, and a blank first line does not authenticate.
190
+ - `<home>/.grok/auth.json` was byte-identical across the authenticated run (`mtime`, `size`, and mode `0600` unchanged), so the probe is a read in that path.
191
+
192
+ These discriminator strings are un-owned vendor UI text.
193
+ `bin/fm-vendor-auth-probe.sh` pins the verified version, reports `versionVerified=no` when the running CLI differs, and classifies any unrecognized first line as `indeterminate` rather than authenticated.
194
+ Re-run the two commands above and update this section and the pinned version together when the vendor CLI changes.
195
+
196
+ ## Regression coverage
197
+
198
+ `tests/fm-vendor-auth-probe.test.sh` drives the real script against a fake vendor CLI that records every invocation's argv and anything readable on stdin.
199
+ It asserts that the script accepts no harness, model, or provider input, never calls `quota-axi`, exits alike for every probe result because it renders no verdict, invokes only the two fixed non-destructive argv forms with stdin closed, holds a real bound even when the configured bound is zero or malformed, and never echoes raw vendor output.
200
+ `tests/fm-spawn-dispatch-profile.test.sh` owns spawn's deterministic profile and harness refusals.
201
+ `tests/fm-bootstrap.test.sh` owns the quota-axi version-floor diagnostic.
202
+ `tests/fm-quota-array-dispatch-live-e2e.test.sh` drives the public Pi skill-loading interface against one fake schema-5 snapshot per case, served as quota-axi's default TOON.
203
+ It covers TOON-first `spendPriority` ranking among candidates that pass eligibility, reasoning-class, and runway-feasibility gates, explicit accounting for unmeasurable runway, the strongest-reasoning constraint, and the runway feasibility floor over a higher `spendPriority`.
204
+ The skill's primary path is that default TOON; `--json` is the documented defensive fallback, and this section records the producer `--json` shape that fallback consumes.
@@ -0,0 +1,221 @@
1
+ # Verification: the muse (Muse Code) crewmate adapter
2
+
3
+ Active empirical evidence for firstmate's muse adapter.
4
+ The skill tree rooted at [`.agents/skills/harness-adapters/SKILL.md`](../../.agents/skills/harness-adapters/SKILL.md) owns the operating facts; this record owns how they were established and what is still unproven.
5
+
6
+ ## Subject
7
+
8
+ | Field | Value |
9
+ |---|---|
10
+ | Version | `Muse Code 0.1.0 (0.1.0-R708.1)`, build sha `427a430436` |
11
+ | Verified | 2026-08-05, extended 2026-08-06 with the credentialed multi-step smoke |
12
+ | Artifact | `muse-aarch64-macos`, sha256 `4290bfafa5bbb81a6fd493aaea12f848c789b1d22edfa0c4b849151deba3e70c` |
13
+ | Platform | macOS arm64 (Darwin 25.5.0) |
14
+
15
+ The binary was fetched from the published channel and its checksum matched the published manifest before any run:
16
+
17
+ ```
18
+ $ curl -sS 'https://api.meta.ai/muse-code/channels/muse-stable'
19
+ {"channel":"muse-stable","version":"0.1.0-R708.1",...,"state":"public","min_version":null}
20
+
21
+ $ shasum -a 256 muse-bin
22
+ 4290bfafa5bbb81a6fd493aaea12f848c789b1d22edfa0c4b849151deba3e70c muse-bin
23
+ ```
24
+
25
+ Every run below used an isolated `XDG_CONFIG_HOME` and `XDG_DATA_HOME` in a scratch directory and a throwaway git workspace, driven through tmux the way firstmate drives a crewmate pane.
26
+ `install.sh` was deliberately bypassed, so no shell profile and no `~/.local/bin` entry on the host was touched.
27
+
28
+ ## What the model provider limits
29
+
30
+ Live TUI and session behavior below was observed against the built-in `--provider echo` startup provider, except for the provider-authentication prompt.
31
+ The credential paths and unauthenticated wait were probed separately against the default `meta` provider.
32
+ Turn-boundary structure, the trust dialog, interrupt, exit, composer rendering, credential behavior, and the event-log schema are real and verified.
33
+ Busy-state behavior under a genuine multi-step, real-model tool loop was verified separately on 2026-08-06 against the default `meta` provider with a live model, and is recorded under [the credentialed multi-step smoke](#the-credentialed-multi-step-smoke-verified-2026-08-06).
34
+
35
+ ## Verified facts
36
+
37
+ ### Process identity
38
+
39
+ The published launcher `exec`s a version-suffixed binary, so the live process name changes on every auto-update:
40
+
41
+ ```
42
+ $ grep -nE 'muse-bin|exec ' launcher.sh
43
+ 969: candidate="$work/muse-bin"
44
+ 977: target="$dir/muse-bin-$version"
45
+ 1035: printf '%s/muse-bin-%s\n' "$dir" "$version"
46
+ 1135: exec "$binary" "$@"
47
+ ```
48
+
49
+ `ps -o comm= -p <pid>` returns the full executable path, whose basename is `muse-bin-<version>`.
50
+ That is why both `bin/fm-harness.sh` and `bin/backends/tmux.sh` match the anchored prefix `muse-bin-*` rather than an exact name, and why neither can rely on an install-path component: `~/.local/bin/muse-bin-<version>` contains no `muse` path component.
51
+ The Muse launch clears `CLAUDECODE`, `PI_CODING_AGENT`, `GROK_AGENT`, `FM_PI_HARNESS`, `CURSOR_AGENT`, and `CURSOR_INVOKED_AS` before the worker starts so foreign primary markers cannot override the versioned ancestry.
52
+
53
+ [`runtime-backends.md`](runtime-backends.md#agent-liveness-name-sources) owns the resulting tmux liveness verdict and its relationship to the portable decoy regression.
54
+
55
+ ### Turn lifecycle
56
+
57
+ A two-turn session produced exactly two run brackets, the second closed by an Escape interrupt:
58
+
59
+ ```
60
+ 9 {"kind":"run","run_id":"d352a097-...","event":{"kind":"started","prompt":"hello from firstmate"}}
61
+ 45 {"kind":"run","run_id":"d352a097-...","event":{"kind":"terminal","terminal":"completed","turn_duration_ms":8152}}
62
+ 49 {"kind":"run","run_id":"b50dac92-...","event":{"kind":"started","prompt":"second turn to interrupt"}}
63
+ 78 {"kind":"run","run_id":"b50dac92-...","event":{"kind":"terminal","terminal":"cancelled","reason":"cancelled during model step"}}
64
+ ```
65
+
66
+ The log's first record carries the workspace binding key:
67
+
68
+ ```
69
+ "payload_type": "runtime.session.metadata",
70
+ "payload": {"kind":"metadata","record":{"workspace_root":".../muselab/ws1","provider_id":"echo",...}}
71
+ ```
72
+
73
+ The fold transitions live, sampled during a 25-second in-flight turn:
74
+
75
+ ```
76
+ T+ 5s fold=busy
77
+ T+10s fold=busy
78
+ T+15s fold=busy
79
+ T+20s fold=busy
80
+ T+25s fold=busy
81
+ T+30s fold=settled
82
+ ```
83
+
84
+ Two decoys were observed in real logs and are pinned by regressions in `tests/fm-muse-harness.test.sh`:
85
+ a nested `"record":{"kind":"terminal"}` cleanup-effect payload that is not a run terminal, and independent sub-agent run lifecycles under `subagent/<child-session-id>/session.jsonl`.
86
+ The same regression suite verifies that unique resolution is cached, a changed current-day main-session namespace restores ambiguity to unknown, a replacement spawn binding selects its fresh main log, missing cached logs fail closed, and cached sub-agent paths are rejected.
87
+
88
+ ### Autonomy, trust, and sandbox
89
+
90
+ A fresh untrusted workspace shows the trust dialog with option 1 preselected:
91
+
92
+ ```
93
+ Do you trust this workspace?
94
+ > 1 Trust and continue
95
+ 2 Quit
96
+ Use Up/Down or 1/2, then Enter. Esc quits.
97
+ ```
98
+
99
+ `--yolo` suppresses it entirely and the status bar reports `echo · <workspace> · YOLO`.
100
+ This matters because approval and the sandbox are ON by default and `--sandbox-network` defaults to `proxy-only`, which the binary reports as requiring managed shell sandboxing - a crewmate needs ordinary git and network access.
101
+
102
+ ### Credentials
103
+
104
+ `muse auth set --provider` accepts only `meta`.
105
+ An unauthenticated launch does not exit; it waits indefinitely:
106
+
107
+ ```
108
+ Sign in at this page:
109
+ https://auth.meta.com/oauth/device/?code=DGXZ-NRPR
110
+ Waiting for approval…
111
+ Esc cancel
112
+ ```
113
+
114
+ That is why `bin/fm-spawn.sh` preflights worker-reachable `META_API_KEY` or `<config>/muse/auth.json` and refuses before creating an endpoint.
115
+ A caller-only `META_API_KEY` is refused because a long-lived backend daemon does not inherit it, while the non-secret `XDG_CONFIG_HOME` and `XDG_DATA_HOME` roots are resolved to absolute paths before preflight and forwarding so the stored credential and session-log binding reach the same worker environment.
116
+
117
+ ### Foreign personal context
118
+
119
+ The interactive TUI rejects the `exec`-only flag:
120
+
121
+ ```
122
+ $ muse --no-foreign-personal-context --provider echo hi
123
+ invalid TUI options: error: unexpected argument '--no-foreign-personal-context' found
124
+ tip: a similar argument exists: '--no-session-log'
125
+ ```
126
+
127
+ `MUSE_EXPERIMENTAL_FOREIGN_PERSONAL_CONTEXT_KILL` is the control that works in TUI mode.
128
+ Comparing the `context_block_diagnostic` block ids emitted by otherwise identical runs, with the operator's real `~/.claude` rules present and no project `AGENTS.md`:
129
+
130
+ ```
131
+ base blocks=rules_file,workspace_identity,security_mode,skills_catalog,session_identity,subagent_delegation
132
+ killon blocks=workspace_identity,security_mode,skills_catalog,session_identity,subagent_delegation
133
+ kill1 blocks=workspace_identity,security_mode,skills_catalog,session_identity,subagent_delegation
134
+ ```
135
+
136
+ Repeating the comparison with a project `AGENTS.md` present confirms the kill switch drops only the FOREIGN rules:
137
+
138
+ ```
139
+ a4base blocks=rules_file,workspace_identity,security_mode,skills_catalog,session_identity,subagent_delegation
140
+ a4kill blocks=rules_file,workspace_identity,security_mode,skills_catalog,session_identity,subagent_delegation
141
+ ```
142
+
143
+ The `tui.foreign_context_notice_shown` flag in `settings.json` suppresses only the notice, never the loading, so a quiet later launch is not evidence of a clean context.
144
+
145
+ ### Composer rendering
146
+
147
+ Captured with `tmux capture-pane -p -e`:
148
+
149
+ ```
150
+ ^[[38;2;90;160;255m^[[48;2;38;56;84m⟩ ^[[38;2;204;211;219mhello from firstmate^[[39m
151
+ ^[[0m^[[38;2;90;160;255m⟩ ^[[39m
152
+ ```
153
+
154
+ Prompt glyph `⟩` (U+27E9) at luminance ~149.9 against the 128 default ghost threshold; typed text at ~209.8.
155
+ After a single Escape the interrupted prompt is restored into the composer at the same bright ~209.8, and `C-u` clears it.
156
+
157
+ ## The credentialed multi-step smoke (verified 2026-08-06)
158
+
159
+ This was the one item deferred until a `META_API_KEY` was available, because it is what decides whether a settled log may classify `idle`.
160
+ An open run was always positive proof of a turn in flight, but a settled log only proves no run is open at that instant, so the classifier held idle behind an opt-in in case a real turn spanned several runs.
161
+ The smoke below answered that: one run brackets a whole multi-step turn, and an Escape interrupt closes that run with `terminal=cancelled` rather than leaving the turn to continue in another run.
162
+ The credentialed result gives a settled Muse log the same idle trust as the Claude and Pi push sources, so the opt-in was removed and `bin/fm-busy-lib.sh` classifies a settled log `idle` outright.
163
+ Muse auto-updates its vendor binary underneath the fleet, firstmate normalizes the versioned process identity to the `muse` harness before busy classification, and the session log's own metadata carries semver `0.1.0` plus a build SHA that cannot be matched to that normalized identity.
164
+ A verified-build allowlist against this coarse identity would be false precision because it could not distinguish the running build, as well as a maintenance treadmill against the auto-updating binary.
165
+
166
+ Both runs below used the default `meta` provider with model `muse-spark-1.2-contributor`, on a real firstmate-launched crewmate pane, authenticated through the stored `~/.config/muse/auth.json` written by `muse auth set --provider meta --api-key-stdin` so the key never entered `argv`.
167
+
168
+ ### One turn stays inside one run
169
+
170
+ A single 8-step tool loop (shell, file reads, a file write, a shell append) ran as one submitted turn in session `629b3bc1-5dd7-4a0d-a901-69701850922c`, log `~/.local/share/muse/sessions/2026/08/06/629b3bc1-5dd7-4a0d-a901-69701850922c/session.jsonl`.
171
+ The whole 828-record turn is bracketed by exactly one run pair, 23 tool batches deep:
172
+
173
+ ```
174
+ $ grep -cE '"kind":"run","run_id":"[^"]*","event":\{"kind":"started"' session.jsonl
175
+ 1
176
+ $ grep -cE '"kind":"run","run_id":"[^"]*","event":\{"kind":"terminal"' session.jsonl
177
+ 1
178
+ $ grep -c '"payload_type":"tool_batch.effect.started"' session.jsonl
179
+ 23
180
+
181
+ 10 {"kind":"run","run_id":"db5869ed-...","event":{"kind":"started","prompt":"...launch-brief..."
182
+ 827 {"kind":"run","run_id":"db5869ed-...","event":{"kind":"terminal","terminal":"completed",
183
+ "reason":null,"turn_duration_ms":75243,"time_to_first_token_ms":69583,"eot_gate_ms":3907}
184
+ ```
185
+
186
+ Scope the count to `"kind":"run"` as above.
187
+ A bare `grep -c '"event":{"kind":"started"'` returns 56 on the same log, because every tool batch effect reuses that inner event shape.
188
+
189
+ ### Busy sampling and interrupt
190
+
191
+ Session `e4e0b4f4-38d0-46dc-b669-dfb5de92e0e0` sampled the fold while a multi-step turn was in flight, then interrupted it with Escape mid tool loop.
192
+ Five consecutive samples of `fm_busy_muse_run_state` on the bound log returned `busy`, and `fm_busy_classify` returned `busy muse-session-log` for the same samples; the fold settled immediately after the interrupt.
193
+ Its run closed as cancelled rather than staying open:
194
+
195
+ ```
196
+ 10 {"kind":"run","run_id":"a098d532-...","event":{"kind":"started","prompt":"...launch-brief..."
197
+ 103 {"kind":"run","run_id":"a098d532-...","event":{"kind":"terminal","terminal":"cancelled",
198
+ "reason":"cancelled during model step","turn_duration_ms":7849}
199
+ ```
200
+
201
+ That is the same terminal shape the `echo`-provider interrupt produced, now confirmed against a live model mid tool loop.
202
+
203
+ `tests/fm-muse-harness.test.sh` pins the resulting classifier behavior: a log settled by either terminal reads `idle`, an open run reads `busy`, and only a resolution failure reads `unknown`.
204
+
205
+ ## Refreshing this record
206
+
207
+ Run both opt-in live guards after any muse upgrade, because the version-suffixed process name, session protocol, and styled composer are vendor-controlled surfaces:
208
+
209
+ ```
210
+ FM_HARNESS_LIVENESS_DRIFT=1 bin/fm-test-run.sh tests/fm-harness-liveness-drift-live-e2e.test.sh
211
+ FM_MUSE_SIGNALS_LIVE=1 bin/fm-test-run.sh tests/fm-muse-signals-live-e2e.test.sh
212
+ ```
213
+
214
+ The Muse signals guard requires a real `muse` binary and tmux but uses `--provider echo`, so it does not require `META_API_KEY` and cannot re-check the real-model turn-to-run relationship on its own.
215
+ The guard follows SGR state through the final prompt glyph and rejects both bright-then-dark and malformed-RGB negative controls before accepting that glyph's effective luminance.
216
+
217
+ muse's launcher can replace the running binary underneath the fleet, so an upgrade that changes the session protocol also invalidates the credentialed evidence above.
218
+ Repeat that smoke after a protocol-affecting upgrade: run one real multi-step tool-loop turn with credentials in place, confirm the run-scoped `started`/`terminal` counts are still exactly one each, and confirm an Escape still yields `terminal` with `cancelled`.
219
+ A build that ever split one turn across several runs would make a settled log ambiguous, which is a classifier change rather than a note in this file.
220
+
221
+ The portable counterparts that run in ordinary CI are `tests/fm-muse-harness.test.sh`, `tests/fm-tmux-agent-liveness.test.sh`, `tests/fm-composer-lib.test.sh`, and `tests/fm-composer-ghost.test.sh`.