Skip to content

feat: Pi-Extension für Crew-Routing und Quota-Balance - #1

Merged
thelad-dev merged 10 commits into
mainfrom
fm/firstmate-crew-knowledge-mvp-20260812
Aug 13, 2026
Merged

feat: Pi-Extension für Crew-Routing und Quota-Balance#1
thelad-dev merged 10 commits into
mainfrom
fm/firstmate-crew-knowledge-mvp-20260812

Conversation

@thelad-dev

@thelad-dev thelad-dev commented Aug 13, 2026

Copy link
Copy Markdown
Owner

Intent

Build the firstmate-crew-knowledge MVP: installable Pi coding-agent extension (npm package, keyword pi-package) integrating with Firstmate for model/harness routing and balanced multi-provider quota across Cursor, Grok (xAI), Claude, ChatGPT/Codex. Complements fm-spawn --harness/--model/--effort, config/crew-dispatch.json, quota-array-dispatch, quota-axi --json; does not fork fleet control plane. Goals: (1) classify tasks (trivial_fix, standard_ship, hard_multi_file, research_web_live, scout_audit) and recommend {harness,model,effort}; (2) live quota-axi balance preferring headroom/runway, avoid exhausted when alternatives exist, never invent credentials; (3) tools crew_route/crew_balance/crew_apply_dispatch, emit Firstmate-schema crew-dispatch.json, spawn flags + rationale, FM_HOME writes dry-run default only under config; (4) data-driven knowledge pack; (5) optional mid-session assist that lists/searches authenticated Pi session models and recommends primary switch target without pi-model-switch or crew pane hijack. Tech: pi.extensions index.ts, TypeBox, quota-axi via child_process, degraded offline heuristic, MIT, German docs + short English README, fixture unit tests. Out of scope: Firstmate core bin/AGENTS changes, auto-spawn, billing automation, perfect fairness under missing quota. Also add GitHub Actions CI running npm test so PR checks can go green (repo previously had zero workflows and CI monitor hung).

What Changed

  • Neue installierbare Pi-Extension (pi-package) mit den Tools crew_route, crew_balance, crew_apply_dispatch und crew_suggest_primary sowie dem Slash-Command /crew-route: klassifiziert Tasks, empfiehlt --harness/--model/--effort und schlägt optional ein Primary-Modell vor, ohne zu spawnen oder Modelle zu wechseln.
  • Datengetriebenes Knowledge-Pack unter knowledge/ plus Live-Balance über quota-axi --json (Headroom/Runway, erschöpfte Provider meiden); fehlt quota-axi, gilt labeled Degraded mit Offline-Heuristik. crew_apply_dispatch erzeugt Firstmate-crew-dispatch.json (Default dry-run, Writes nur unter $FM_HOME/config).
  • GitHub-Actions-Workflow führt npm test aus; Fixture-Unit-Tests decken Scorer, Quota, Dispatch, FM-Home und Primary-Suggest ab.

Risk Assessment

⚠️ Medium: The MVP is a well-bounded new Pi package whose previously reported stale-quota, merge-overwrite, ENOENT, and abort defects are fixed in source; residual risk is the inherent child_process and FM_HOME write surface, not a remaining concrete defect.

Testing

Ran the package’s focused Node test suite, then exercised the real Pi extension tools and public routing/balance/dispatch APIs end-to-end: all five task classes produced --harness/--model/--effort flags, exhausted Claude lost to Codex, live quota-axi --json was consumed without inventing credentials, default apply-dispatch stayed dry-run while an explicit write landed only under FM_HOME/config, and the CI workflow model runs npm test on Node 22. No screenshot or rendered HTML was captured because this change has no browser/Electron/CSS surface; the user-facing product is Pi tool text and JSON, saved as transcripts.

Evidence: All five task classes → spawn flags (balanced fixture)

trivial_fix → --harness codex --model gpt-5.5 --effort low standard_ship → --harness codex --model gpt-5.5 --effort medium hard_multi_file → --harness codex --model gpt-5.5 --effort high research_web_live → --harness grok --model latest --effort medium scout_audit → --harness codex --model gpt-5.5 --effort medium

| task | classified as | spawn | provider |
| --- | --- | --- | --- |
| trivial_fix | trivial_fix (conf=high) | `--harness codex --model gpt-5.5 --effort low` | codex |
| standard_ship | standard_ship (conf=high) | `--harness codex --model gpt-5.5 --effort medium` | codex |
| hard_multi_file | hard_multi_file (conf=high) | `--harness codex --model gpt-5.5 --effort high` | codex |
| research_web_live | research_web_live (conf=high) | `--harness grok --model latest --effort medium` | grok |
| scout_audit | scout_audit (conf=high) | `--harness codex --model gpt-5.5 --effort medium` | codex |

# crew_route — fixture quota-balanced

### trivial_fix

# crew_route

Task-Klasse: trivial_fix (Trivial fix)
Klassifikation: high — Keyword-Treffer (3): typo, rename, one-liner
Modus: live
Quota-Kurz: claude:12%/ok, codex:70%/ok, cursor:unk/ok, grok:55%/ok

## Empfehlung
spawn: --harness codex --model gpt-5.5 --effort low
profile: cheap-fast-codex
tradeoff: Qualität low/fast; Headroom 70% (all_models); Runway ~24h
why: Low-effort Codex for trivial mechanical edits.
evidence:
  - profile=cheap-fast-codex
  - provider=codex
  - quality=low (floor low)
  - list=preferred
  - Low-effort Codex for trivial mechanical edits.
  - state=fresh; fresh-or-n/a; semantics=known; scope=all_models; effectiveRemaining=70%; runwaySeconds=86400
  - headroom_term=28.0
  - runway_term=12.0 (24.0h)

## Alternativen
- --harness cursor --model auto --effort low  [cursor-auto] score=158.5 — Qualität low/fast; Headroom unbekannt (eligible)
- --harness claude --model haiku --effort low  [cheap-fast-claude] score=157.3 — Qualität low/fast; Headroom 12% (all_models); Runway ~2h
- --harness codex --model gpt-5.5 --effort medium  [standard-codex] score=140.5 — Qualität medium/standard; Headroom 70% (all_models); Runway ~24h
- --harness pi --model anthropic/claude-sonnet-4 --effort medium  [standard-pi-sonnet] score=106.2 — Qualität medium/standard; Headroom 12% (all_models); Runway ~2h

## Hinweis
Empfehlung nur — ersetzt weder Firstmate-Urteil noch quota-array-dispatch. Firstmate übergibt konkrete Flags an fm-spawn.

### standard_ship

# crew_route

Task-Klasse: standard_ship (Standard ship)
Klassifikation: high — Keyword-Treffer (5): feature, implement, pr, open a pr, standard
Modus: live
Quota-Kurz: claude:12%/ok, codex:70%/ok, cursor:unk/ok, grok:55%/ok

## Empfehlung
spawn: --harness codex --model gpt-5.5 --effort medium
profile: standard-codex
tradeoff: Qualität medium/standard; Headroom 70% (all_models); Runway ~24h
why: Default steady ship profile on Codex.
evidence:
  - profile=standard-codex
  - provider=codex
  - quality=medium (floor medium)
  - list=preferred
  - Default steady ship profile on Codex.
  - state=fresh; fresh-or-n/a; semantics=known; scope=all_models; effectiveRemaining=70%; runwaySeconds=86400
  - headroom_term=28.0
  - runway_term=12.0 (24.0h)

## Alternativen
- --harness cursor --model composer --effort medium  [cursor-composer] score=158.5 — Qualität medium/standard; Headroom unbekannt (eligible)
- --harness pi --model anthropic/claude-sonnet-4 --effort medium  [standard-pi-sonnet] score=157.3 — Qualität medium/standard; Headroom 12% (all_models); Runway ~2h
- --harness claude --model sonnet --effort medium  [standard-claude] score=156.8 — Qualität medium/standard; Headroom 12% (all_models); Runway ~2h
- --harness codex --model gpt-5.5 --effort high  [strong-codex] score=140.4 — Qualität high/strong; Headroom 70% (all_models); Runway ~24h
- --harness claude --model claude-sonnet-4 --effort high  [strong-claude] score=106.3 — Qualität high/strong; Headroom 12% (all_models); Runway ~2h

## Hinweis
Empfehlung nur — ersetzt weder Firstmate-Urteil noch quota-array-dispatch. Firstmate übergibt konkrete Flags an fm-spawn.

### hard_multi_file

# crew_route

Task-Klasse: hard_multi_file (Hard multi-file)
Klassifikation: high — Keyword-Treffer (4): refactor, multi-file, architecture, ambiguous
Modus: live
Quota-Kurz: claude:12%/ok, codex:70%/ok, cursor:unk/ok, grok:55%/ok

## Empfehlung
spawn: --harness codex --model gpt-5.5 --effort high
profile: strong-codex
tradeoff: Qualität high/strong; Headroom 70% (all_models); Runway ~24h
why: High-effort Codex for hard multi-file features.
evidence:
  - profile=strong-codex
  - provider=codex
  - quality=high (floor high)
  - list=preferred
  - High-effort Codex for hard multi-file features.
  - state=fresh; fresh-or-n/a; semantics=known; scope=all_models; effectiveRemaining=70%; runwaySeconds=86400
  - headroom_term=28.0
  - runway_term=12.0 (24.0h)

## Alternativen
- --harness cursor --model composer --effort high  [cursor-composer-high] score=158.5 — Qualität high/strong; Headroom unbekannt (eligible)
- --harness claude --model claude-sonnet-4 --effort high  [strong-claude] score=157.8 — Qualität high/strong; Headroom 12% (all_models); Runway ~2h
- --harness pi --model anthropic/claude-opus-4 --effort high  [strong-pi-opus] score=156.8 — Qualität high/strong; Headroom 12% (all_models); Runway ~2h
- --harness codex --model gpt-5.5 --effort medium  [standard-codex] score=-9.5 — unter Quality-Floor; Headroom 70% (all_models); Runway ~24h
- --harness claude --model sonnet --effort medium  [standard-claude] score=-43.8 — unter Quality-Floor; Headroom 12% (all_models); Runway ~2h

## Hinweis
Empfehlung nur — ersetzt weder Firstmate-Urteil noch quota-array-dispatch. Firstmate übergibt konkrete Flags an fm-spawn.

### research_web_live

# crew_route

Task-Klasse: research_web_live (Research / web-live)
Klassifikation: high — Keyword-Treffer (6): web research, live web, current market news, latest news, news today, market news
Modus: live
Quota-Kurz: claude:12%/ok, codex:70%/ok, cursor:unk/ok, grok:55%/ok

## Empfehlung
spawn: --harness grok --model latest --effort medium
profile: grok-research
tradeoff: Qualität medium/research; Headroom 55% (all_models); Runway-Status through_reset
why: Native Grok when live/public web context is central.
evidence:
  - profile=grok-research
  - provider=grok
  - quality=medium (floor medium)
  - list=preferred
  - Native Grok when live/public web context is central.
  - state=fresh; fresh-or-n/a; semantics=known; scope=all_models; effectiveRemaining=55%; runway=through_reset; authStatus=usable
  - headroom_term=22.0
  - runway_term=unknown

## Alternativen
- --harness pi --model xai/grok-4 --effort medium  [pi-grok-research] score=172.5 — Qualität medium/research; Headroom 55% (all_models); Runway-Status through_reset
- --harness codex --model gpt-5.5 --effort medium  [standard-codex] score=140.4 — Qualität medium/standard; Headroom 70% (all_models); Runway ~24h
- --harness pi --model anthropic/claude-sonnet-4 --effort medium  [standard-pi-sonnet] score=106.3 — Qualität medium/standard; Headroom 12% (all_models); Runway ~2h

## Hinweis
Empfehlung nur — ersetzt weder Firstmate-Urteil noch quota-array-dispatch. Firstmate übergibt konkrete Flags an fm-spawn.

### scout_audit

# crew_route

Task-Klasse: scout_audit (Scout / audit)
Klassifikation: high — Keyword-Treffer (4): scout, audit, inventory, risk scan
Modus: live
Quota-Kurz: claude:12%/ok, codex:70%/ok, cursor:unk/ok, grok:55%/ok

## Empfehlung
spawn: --harness codex --model gpt-5.5 --effort medium
profile: scout-codex
tradeoff: Qualität medium/scout; Headroom 70% (all_models); Runway ~24h
why: Read-oriented Codex scout profile.
evidence:
  - profile=scout-codex
  - provider=codex
  - quality=medium (floor medium)
  - list=preferred
  - Read-oriented Codex scout profile.
  - state=fresh; fresh-or-n/a; semantics=known; scope=all_models; effectiveRemaining=70%; runwaySeconds=86400
  - headroom_term=28.0
  - runway_term=12.0 (24.0h)

## Alternativen
- --harness cursor --model auto --effort low  [cursor-scout] score=158.5 — Qualität medium/scout; Headroom unbekannt (eligible)
- --harness claude --model sonnet --effort medium  [scout-claude] score=157.3 — Qualität medium/scout; Headroom 12% (all_models); Runway ~2h
- --harness pi --model anthropic/claude-sonnet-4 --effort low  [scout-pi] score=156.8 — Qualität medium/scout; Headroom 12% (all_models); Runway ~2h
- --harness codex --model gpt-5.5 --effort medium  [standard-codex] score=140.5 — Qualität medium/standard; Headroom 70% (all_models); Runway ~24h
- --harness claude --model haiku --effort low  [cheap-fast-claude] score=-43.8 — unter Quality-Floor; Headroom 12% (all_models); Runway ~2h

## Hinweis
Empfehlung nur — ersetzt weder Firstmate-Urteil noch quota-array-dispatch. Firstmate übergibt konkrete Flags an fm-spawn.
Evidence: crew_route avoids exhausted Claude (hard_multi_file)
# crew_route

Task-Klasse: hard_multi_file (Hard multi-file)
Klassifikation: high — Keyword-Treffer (4): refactor, multi-file, architecture, ambiguous
Modus: live
Quota-Kurz: claude:0%/!exhausted, codex:80%/ok, grok:unk/ok, cursor:unk/!exhausted

## Empfehlung
spawn: --harness codex --model gpt-5.5 --effort high
profile: strong-codex
tradeoff: Qualität high/strong; Headroom 80% (all_models); Runway ~48h
why: High-effort Codex for hard multi-file features.
evidence:
  - profile=strong-codex
  - provider=codex
  - quality=high (floor high)
  - list=preferred
  - High-effort Codex for hard multi-file features.
  - state=fresh; fresh-or-n/a; semantics=known; scope=all_models; effectiveRemaining=80%; runwaySeconds=172800
  - headroom_term=32.0
  - runway_term=24.0 (48.0h)

## Alternativen
- --harness cursor --model composer --effort high  [cursor-composer-high] score=78.5 — Qualität high/strong; Quota erschöpft/0
- --harness claude --model claude-sonnet-4 --effort high  [strong-claude] score=72.0 — Qualität high/strong; Quota erschöpft/0; Runway ~0h
- --harness pi --model anthropic/claude-opus-4 --effort high  [strong-pi-opus] score=71.0 — Qualität high/strong; Quota erschöpft/0; Runway ~0h
- --harness codex --model gpt-5.5 --effort medium  [standard-codex] score=6.5 — unter Quality-Floor; Headroom 80% (all_models); Runway ~48h
- --harness claude --model sonnet --effort medium  [standard-claude] score=-129.6 — unter Quality-Floor; Quota erschöpft/0; Runway ~0h

## Hinweis
Empfehlung nur — ersetzt weder Firstmate-Urteil noch quota-array-dispatch. Firstmate übergibt konkrete Flags an fm-spawn.
Evidence: crew_balance ranks exhausted Claude last
# crew_balance

Modus: live
Snapshot: 2026-08-12T12:00:00.000Z

## Provider (sortiert)
- codex: headroom=80% runway=48h exhausted=false state=fresh
  evidence: state=fresh; fresh-or-n/a; semantics=known; scope=all_models; effectiveRemaining=80%; runwaySeconds=172800
- grok: headroom=unknown runway=unknown exhausted=false state=unavailable
  evidence: state=unavailable; fresh-or-n/a; semantics=unknown; effectiveRemaining=unknown; runway=unknown; authStatus=usable; error=Grok consumer quota unavailable
- claude: headroom=0% runway=0h exhausted=true state=fresh
  evidence: state=fresh; fresh-or-n/a; semantics=known; scope=all_models; effectiveRemaining=0%; runwaySeconds=0
- cursor: headroom=unknown runway=unknown exhausted=true state=fresh
  evidence: state=fresh; fresh-or-n/a; semantics=unknown; effectiveRemaining=unknown; runway=unknown

## Notes
- Sortierung: bekanntes Headroom desc, dann Runway; exhausted zuletzt; unknown bleibt eligible.
- Prozentwerte sind provider-intern und nicht cross-provider vergleichbar — nur relative Preferenz.

Empfehlung nur — ersetzt weder Firstmate-Urteil noch quota-array-dispatch. Firstmate übergibt konkrete Flags an fm-spawn.
Evidence: Live quota-axi crew_balance (no invented credentials)
# crew_balance

Modus: live
Snapshot: 2026-08-13T11:50:08.977Z

## Provider (sortiert)
- claude: headroom=unknown runway=unknown exhausted=false state=auth_required
  evidence: state=auth_required; fresh-or-n/a; semantics=unknown; effectiveRemaining=unknown; runway=unknown; error=credentials_missing
- codex: headroom=unknown runway=unknown exhausted=false state=error
  evidence: state=error; fresh-or-n/a; semantics=unknown; effectiveRemaining=unknown; runway=unknown; error=Codex quota unavailable
- copilot: headroom=unknown runway=unknown exhausted=false state=auth_required
  evidence: state=auth_required; fresh-or-n/a; semantics=unknown; effectiveRemaining=unknown; runway=unknown; error=GitHub Copilot sign-in required
- grok: headroom=unknown runway=unknown exhausted=false state=unavailable
  evidence: state=unavailable; fresh-or-n/a; semantics=unknown; effectiveRemaining=unknown; runway=unknown; authStatus=usable; error=Grok consumer quota unavailable
- kimi: headroom=unknown runway=unknown exhausted=false state=auth_required
  evidence: state=auth_required; fresh-or-n/a; semantics=unknown; effectiveRemaining=unknown; runway=unknown; error=kimi_credential_unavailable
- cursor: headroom=unknown runway=unknown exhausted=true state=fresh
  evidence: state=fresh; fresh-or-n/a; semantics=unknown; effectiveRemaining=unknown; runway=unknown

## Notes
- Sortierung: bekanntes Headroom desc, dann Runway; exhausted zuletzt; unknown bleibt eligible.
- Prozentwerte sind provider-intern und nicht cross-provider vergleichbar — nur relative Preferenz.

Empfehlung nur — ersetzt weder Firstmate-Urteil noch quota-array-dispatch. Firstmate übergibt konkrete Flags an fm-spawn.
Evidence: Live quota-axi --json snapshot
{
  "generatedAt": "2026-08-13T11:50:08.977Z",
  "schemaVersion": 3,
  "providers": [
    {
      "provider": "claude",
      "label": "Claude",
      "source": "unavailable",
      "windows": [],
      "state": {
        "status": "auth_required",
        "stale": false,
        "error": "credentials_missing",
        "sourcesTried": [
          "oauth-file"
        ]
      },
      "quotaSemantics": {
        "status": "unknown",
        "description": "No quota windows are available, so no effective remaining percentage can be computed.",
        "effectiveAvailability": []
      }
    },
    {
      "provider": "codex",
      "label": "Codex",
      "source": "unavailable",
      "windows": [],
      "state": {
        "status": "error",
        "stale": false,
        "error": "Codex quota unavailable",
        "sourcesTried": [
          "oauth",
          "cli-rpc"
        ]
      },
      "quotaSemantics": {
        "status": "unknown",
        "description": "No quota windows are available, so no effective remaining percentage can be computed.",
        "effectiveAvailability": []
      }
    },
    {
      "provider": "cursor",
      "label": "Cursor",
      "source": "api",
      "plan": "Pro",
      "windows": [
        {
          "id": "included_usage",
          "label": "included usage",
          "kind": "monthly",
          "percentUsed": 100,
          "resetsAt": "2026-09-01T09:10:20.000Z",
          "percentRemaining": 0,
          "pace": {
            "status": "unknown",
            "reason": "missing_cycle"
          }
        },
        {
          "id": "auto_usage",
          "label": "auto usage",
          "kind": "monthly",
          "percentUsed": 100,
          "resetsAt": "2026-09-01T09:10:20.000Z",
          "percentRemaining": 0,
          "pace": {
            "status": "unknown",
            "reason": "missing_cycle"
          }
        },
        {
          "id": "api_usage",
          "label": "API usage",
          "kind": "monthly",
          "percentUsed": 100,
          "resetsAt": "2026-09-01T09:10:20.000Z",
          "percentRemaining": 0,
          "pace": {
            "status": "unknown",
            "reason": "missing_cycle"
          }
        }
      ],
      "state": {
        "status": "fresh",
        "stale": false,
        "refreshedAt": "2026-08-13T11:50:09.412Z",
        "sourcesTried": [
          "api"
        ]
      },
      "quotaSemantics": {
        "status": "unknown",
        "description": "quota-axi does not know whether Cursor's reported windows are independent or jointly bounding, so it does not claim an effective remaining percentage.",
        "effectiveAvailability": [],
        "unresolvedWindowIds": [
          "included_usage",
          "auto_usage",
          "api_usage"
        ]
      }
    },
    {
      "provider": "copilot",
      "label": "GitHub Copilot",
      "source": "unavailable",
      "windows": [],
      "state": {
        "status": "auth_required",
        "stale": false,
        "error": "GitHub Copilot sign-in required",
        "sourcesTried": [
          "apps-json"
        ]
      },
      "quotaSemantics": {
        "status": "unknown",
        "description": "No quota windows are available, so no effective remaining percentage can be computed.",
        "effectiveAvailability": [],
        "unresolvedWindowIds": []
      }
    },
    {
      "provider": "grok",
      "label": "Grok",
      "source": "unavailable",
      "windows": [],
      "state": {
        "status": "unavailable",
        "stale": false,
        "error": "Grok consumer quota unavailable",
        "sourcesTried": [
          "auth-json",
          "pi:xai"
        ],
        "authStatus": "usable"
      },
      "quotaSemantics": {
        "status": "unknown",
        "description": "No quota windows are available, so no effective remaining percentage can be computed.",
        "effectiveAvailability": []
      }
    },
    {
      "provider": "kimi",
      "label": "Kimi",
      "source": "unavailable",
      "windows": [],
      "state": {
        "status": "auth_required",
        "stale": false,
        "error": "kimi_credential_unavailable",
        "sourcesTried": [
          "pi:kimi-coding",
          "kimi-code-cli"
        ]
      },
      "quotaSemantics": {
        "status": "unknown",
        "description": "No quota windows are available, so no effective remaining percentage can be computed.",
        "effectiveAvailability": []
      }
    }
  ]
}
Evidence: Generated Firstmate-schema crew-dispatch.json
{
  "rules": [
    {
      "when": "The task depends on fresh news, current events, live public facts, or recent market and product changes.",
      "use": [
        {
          "harness": "grok",
          "model": "latest",
          "effort": "medium"
        },
        {
          "harness": "pi",
          "model": "xai/grok-4",
          "effort": "medium"
        }
      ],
      "why": "Grok is preferred when current web-connected context is central; resolve alternatives through quota-aware choice."
    },
    {
      "when": "The task is a trivial mechanical edit such as a rote rename, formatting sweep, targeted typo fix, or simple file gathering.",
      "use": [
        {
          "harness": "claude",
          "model": "haiku",
          "effort": "low"
        },
        {
          "harness": "codex",
          "model": "gpt-5.5",
          "effort": "low"
        }
      ],
      "why": "Use the cheapest fast profile when the task is narrow and low ambiguity."
    },
    {
      "when": "The task is a big or ambiguous multi-file feature, a risky refactor, or work that requires holding many moving parts in mind.",
      "use": [
        {
          "harness": "claude",
          "model": "claude-sonnet-4",
          "effort": "high"
        },
        {
          "harness": "codex",
          "model": "gpt-5.5",
          "effort": "high"
        }
      ],
      "why": "Use a strong coding profile for big, ambiguous work; resolve the alternatives through quota-array-dispatch."
    },
    {
      "when": "The task is a read-only scout, audit, inventory, or risk scan without shipping code.",
      "use": [
        {
          "harness": "codex",
          "model": "gpt-5.5",
          "effort": "medium"
        },
        {
          "harness": "claude",
          "model": "sonnet",
          "effort": "medium"
        }
      ],
      "why": "Prefer medium read-oriented profiles for scouts; keep burn modest."
    }
  ],
  "default": [
    {
      "harness": "codex",
      "model": "gpt-5.5",
      "effort": "medium"
    },
    {
      "harness": "pi",
      "model": "anthropic/claude-sonnet-4",
      "effort": "medium"
    },
    {
      "harness": "claude",
      "model": "sonnet",
      "effort": "medium"
    }
  ]
}
Evidence: Explicit FM_HOME/config write of crew-dispatch.json
{
  "rules": [
    {
      "when": "The task depends on fresh news, current events, live public facts, or recent market and product changes.",
      "use": [
        {
          "harness": "grok",
          "model": "latest",
          "effort": "medium"
        },
        {
          "harness": "pi",
          "model": "xai/grok-4",
          "effort": "medium"
        }
      ],
      "why": "Grok is preferred when current web-connected context is central; resolve alternatives through quota-aware choice."
    },
    {
      "when": "The task is a trivial mechanical edit such as a rote rename, formatting sweep, targeted typo fix, or simple file gathering.",
      "use": [
        {
          "harness": "claude",
          "model": "haiku",
          "effort": "low"
        },
        {
          "harness": "codex",
          "model": "gpt-5.5",
          "effort": "low"
        }
      ],
      "why": "Use the cheapest fast profile when the task is narrow and low ambiguity."
    },
    {
      "when": "The task is a big or ambiguous multi-file feature, a risky refactor, or work that requires holding many moving parts in mind.",
      "use": [
        {
          "harness": "claude",
          "model": "claude-sonnet-4",
          "effort": "high"
        },
        {
          "harness": "codex",
          "model": "gpt-5.5",
          "effort": "high"
        }
      ],
      "why": "Use a strong coding profile for big, ambiguous work; resolve the alternatives through quota-array-dispatch."
    },
    {
      "when": "The task is a read-only scout, audit, inventory, or risk scan without shipping code.",
      "use": [
        {
          "harness": "codex",
          "model": "gpt-5.5",
          "effort": "medium"
        },
        {
          "harness": "claude",
          "model": "sonnet",
          "effort": "medium"
        }
      ],
      "why": "Prefer medium read-oriented profiles for scouts; keep burn modest."
    }
  ],
  "default": [
    {
      "harness": "codex",
      "model": "gpt-5.5",
      "effort": "medium"
    },
    {
      "harness": "pi",
      "model": "anthropic/claude-sonnet-4",
      "effort": "medium"
    },
    {
      "harness": "claude",
      "model": "sonnet",
      "effort": "medium"
    }
  ]
}
Evidence: crew_apply_dispatch dry-run transcript
# crew_apply_dispatch

Dry-run OK. Would write /tmp/no-mistakes-evidence/01KZWZX6EYEXG8C1AFMG5TRSP2/fm-home-dry/config/crew-dispatch.json. Pass dryRun=false for explicit write under FM_HOME/config.
path: /tmp/no-mistakes-evidence/01KZWZX6EYEXG8C1AFMG5TRSP2/fm-home-dry/config/crew-dispatch.json
dryRun: true
wrote: false
validation: ok

## crew-dispatch.json
`` `json
{
  "rules": [
    {
      "when": "The task depends on fresh news, current events, live public facts, or recent market and product changes.",
      "use": [
        {
          "harness": "grok",
          "model": "latest",
          "effort": "medium"
        },
        {
          "harness": "pi",
          "model": "xai/grok-4",
          "effort": "medium"
        }
      ],
      "why": "Grok is preferred when current web-connected context is central; resolve alternatives through quota-aware choice."
    },
    {
      "when": "The task is a trivial mechanical edit such as a rote rename, formatting sweep, targeted typo fix, or simple file gathering.",
      "use": [
        {
          "harness": "claude",
          "model": "haiku",
          "effort": "low"
        },
        {
          "harness": "codex",
          "model": "gpt-5.5",
          "effort": "low"
        }
      ],
      "why": "Use the cheapest fast profile when the task is narrow and low ambiguity."
    },
    {
      "when": "The task is a big or ambiguous multi-file feature, a risky refactor, or work that requires holding many moving parts in mind.",
      "use": [
        {
          "harness": "claude",
          "model": "claude-sonnet-4",
          "effort": "high"
        },
        {
          "harness": "codex",
          "model": "gpt-5.5",
          "effort": "high"
        }
      ],
      "why": "Use a strong coding profile for big, ambiguous work; resolve the alternatives through quota-array-dispatch."
    },
    {
      "when": "The task is a read-only scout, audit, inventory, or risk scan without shipping code.",
      "use": [
        {
          "harness": "codex",
          "model": "gpt-5.5",
          "effort": "medium"
        },
        {
          "harness": "claude",
          "model": "sonnet",
          "effort": "medium"
        }
      ],
      "why": "Prefer medium read-oriented profiles for scouts; keep burn modest."
    }
  ],
  "default": [
    {
      "harness": "codex",
      "model": "gpt-5.5",
      "effort": "medium"
    },
    {
      "harness": "pi",
      "model": "anthropic/claude-sonnet-4",
      "effort": "medium"
    },
    {
      "harness": "claude",
      "model": "sonnet",
      "effort": "medium"
    }
  ]
}
`` `

Firstmate liest diese Datei bei Intake, wählt die passende Regel und löst Arrays über quota-array-dispatch auf, bevor fm-spawn konkrete Flags bekommt.
Evidence: crew_suggest_primary advisory (no switch)
# crew_suggest_primary

Goal: implement a standard feature and open a PR
Search: (none)
Suggested class: standard_ship
Mode: live
Session models: 4 (available)
Current: anthropic/claude-sonnet-4

## Recommendation (advisory)
switch target: openai-codex/gpt-5.5
name: GPT
aligned profile: standard-codex
tradeoff: session model openai-codex/gpt-5.5; profile standard-codex; Headroom 70%
why: profile-match standard-codex (+120); headroom +17.5

## Alternatives in session
- anthropic/claude-sonnet-4 [standard-pi-sonnet] score=100.0 — profile-match standard-pi-sonnet (+96); headroom +3.0; currently active
- anthropic/claude-opus-4 [standard-pi-sonnet] score=47.0 — provider-family claude via standard-pi-sonnet (+44); headroom +3.0
- xai/grok-4 score=13.8 — headroom +13.8

## Notes
- Filtered to models with configured auth.
- Task-Klasse (advisory): standard_ship (high)
- Keyword-Treffer (5): feature, implement, pr, open a pr, standard
- Empfehlung nur unter in dieser Session sichtbaren/authentifizierten Pi-Modellen.

Advisory only — schaltet kein Modell und berührt keine Crew-Panes. Manuell /model oder optionales pi-model-switch nutzen.
Evidence: Real Pi tool crew_route output
# crew_route

Task-Klasse: standard_ship (Standard ship)
Klassifikation: high — Keyword-Treffer (5): feature, implement, pr, open a pr, standard
Modus: live
Quota-Kurz: claude:unk/ok, codex:unk/ok, cursor:unk/!exhausted, copilot:unk/ok, grok:unk/ok, kimi:unk/ok

## Empfehlung
spawn: --harness codex --model gpt-5.5 --effort medium
profile: standard-codex
tradeoff: Qualität medium/standard; Headroom unbekannt (eligible)
why: Default steady ship profile on Codex.
evidence:
  - profile=standard-codex
  - provider=codex
  - quality=medium (floor medium)
  - list=preferred
  - Default steady ship profile on Codex.
  - state=error; fresh-or-n/a; semantics=unknown; effectiveRemaining=unknown; runway=unknown; error=Codex quota unavailable
  - headroom_term=unknown_eligible(+8)
  - runway_term=unknown

## Alternativen
- --harness pi --model anthropic/claude-sonnet-4 --effort medium  [standard-pi-sonnet] score=144.5 — Qualität medium/standard; Headroom unbekannt (eligible)
- --harness claude --model sonnet --effort medium  [standard-claude] score=144.0 — Qualität medium/standard; Headroom unbekannt (eligible)
- --harness cursor --model composer --effort medium  [cursor-composer] score=138.5 — Qualität medium/standard; Quota erschöpft/0
- --harness codex --model gpt-5.5 --effort high  [strong-codex] score=108.4 — Qualität high/strong; Headroom unbekannt (eligible)
- --harness claude --model claude-sonnet-4 --effort high  [strong-claude] score=93.5 — Qualität high/strong; Headroom unbekannt (eligible)

## Hinweis
Empfehlung nur — ersetzt weder Firstmate-Urteil noch quota-array-dispatch. Firstmate übergibt konkrete Flags an fm-spawn.
Evidence: Real Pi tool crew_apply_dispatch dry-run
# crew_apply_dispatch

Dry-run OK. Would write /tmp/no-mistakes-evidence/01KZWZX6EYEXG8C1AFMG5TRSP2/fm-home-tool-dry/config/crew-dispatch.json. Pass dryRun=false for explicit write under FM_HOME/config.
path: /tmp/no-mistakes-evidence/01KZWZX6EYEXG8C1AFMG5TRSP2/fm-home-tool-dry/config/crew-dispatch.json
dryRun: true
wrote: false
validation: ok

## crew-dispatch.json
`` `json
{
  "rules": [
    {
      "when": "The task depends on fresh news, current events, live public facts, or recent market and product changes.",
      "use": [
        {
          "harness": "grok",
          "model": "latest",
          "effort": "medium"
        },
        {
          "harness": "pi",
          "model": "xai/grok-4",
          "effort": "medium"
        }
      ],
      "why": "Grok is preferred when current web-connected context is central; resolve alternatives through quota-aware choice."
    },
    {
      "when": "The task is a trivial mechanical edit such as a rote rename, formatting sweep, targeted typo fix, or simple file gathering.",
      "use": [
        {
          "harness": "claude",
          "model": "haiku",
          "effort": "low"
        },
        {
          "harness": "codex",
          "model": "gpt-5.5",
          "effort": "low"
        }
      ],
      "why": "Use the cheapest fast profile when the task is narrow and low ambiguity."
    },
    {
      "when": "The task is a big or ambiguous multi-file feature, a risky refactor, or work that requires holding many moving parts in mind.",
      "use": [
        {
          "harness": "claude",
          "model": "claude-sonnet-4",
          "effort": "high"
        },
        {
          "harness": "codex",
          "model": "gpt-5.5",
          "effort": "high"
        }
      ],
      "why": "Use a strong coding profile for big, ambiguous work; resolve the alternatives through quota-array-dispatch."
    },
    {
      "when": "The task is a read-only scout, audit, inventory, or risk scan without shipping code.",
      "use": [
        {
          "harness": "codex",
          "model": "gpt-5.5",
          "effort": "medium"
        },
        {
          "harness": "claude",
          "model": "sonnet",
          "effort": "medium"
        }
      ],
      "why": "Prefer medium read-oriented profiles for scouts; keep burn modest."
    }
  ],
  "default": [
    {
      "harness": "codex",
      "model": "gpt-5.5",
      "effort": "medium"
    },
    {
      "harness": "pi",
      "model": "anthropic/claude-sonnet-4",
      "effort": "medium"
    },
    {
      "harness": "claude",
      "model": "sonnet",
      "effort": "medium"
    }
  ]
}
`` `

Firstmate liest diese Datei bei Intake, wählt die passende Regel und löst Arrays über quota-array-dispatch auf, bevor fm-spawn konkrete Flags bekommt.
Evidence: Mock Pi extension registration and tool calls

Source: Mock Pi extension registration and tool calls (local file: /tmp/no-mistakes-evidence/01KZWZX6EYEXG8C1AFMG5TRSP2/mock-pi-extension.json)

tools: crew_route, crew_balance, crew_apply_dispatch, crew_suggest_primary; command /crew-route; default apply-dispatch did not write
Evidence: CI workflow semantic model
{
  "name": "ci",
  "on_keys": [
    "push",
    "pull_request"
  ],
  "push_branches": [
    "main",
    "master"
  ],
  "has_pull_request": true,
  "job_ids": [
    "test"
  ],
  "runs_on": "ubuntu-latest",
  "timeout_minutes": 15,
  "uses": [
    "actions/checkout@v4",
    "actions/setup-node@v4"
  ],
  "run_cmds": [
    "npm install --no-fund --no-audit",
    "npm test"
  ],
  "node_version": "22",
  "runs_npm_test": true,
  "installs_deps": true
}
Evidence: Degraded offline heuristic route
# crew_route

Task-Klasse: trivial_fix (Trivial fix)
Klassifikation: high — Explizite Klasse: trivial_fix
Modus: degraded — quota-axi not found on PATH
Quota-Kurz: degraded: quota-axi not found on PATH

## Empfehlung
spawn: --harness claude --model haiku --effort low
profile: cheap-fast-claude
tradeoff: Qualität ok; Quota offline/unbekannt — Knowledge-Reihenfolge.
why: Cheapest fast Claude profile for narrow mechanical work.
evidence:
  - profile=cheap-fast-claude
  - provider=claude
  - quality=low (floor low)
  - list=preferred
  - Cheapest fast Claude profile for narrow mechanical work.
  - quota=degraded/offline heuristic

## Alternativen
- --harness codex --model gpt-5.5 --effort low  [cheap-fast-codex] score=156.0 — Qualität ok; Quota offline/unbekannt — Knowledge-Reihenfolge.
- --harness cursor --model auto --effort low  [cursor-auto] score=155.5 — Qualität ok; Quota offline/unbekannt — Knowledge-Reihenfolge.
- --harness codex --model gpt-5.5 --effort medium  [standard-codex] score=105.5 — Qualität ok; Quota offline/unbekannt — Knowledge-Reihenfolge.
- --harness pi --model anthropic/claude-sonnet-4 --effort medium  [standard-pi-sonnet] score=105.4 — Qualität ok; Quota offline/unbekannt — Knowledge-Reihenfolge.

## Hinweis
Empfehlung nur — ersetzt weder Firstmate-Urteil noch quota-array-dispatch. Firstmate übergibt konkrete Flags an fm-spawn.

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

🔧 **Review** - 4 issues found → auto-fixed (2) ✅
  • ⚠️ src/quota.ts:101 - summarizeProvider skips stale effectiveAvailability/runway (the intended invariant: do not route from stale raw percentages) but still sets exhausted=true from raw windows when every numeric percentRemaining is <= 0. Reachable path: quota-axi returns stale=true, semantics unused, windows all at 0 → exhausted=true → rankCandidates applies penalty=exhausted_while_alternatives_exist (-80) and steers crew_route/crew_balance/crew_suggest_primary away from a recovered provider. Gate the window-exhaustion fallback on !stale at the same boundary as the effectiveRemaining skip (line 72).
  • ⚠️ src/dispatch.ts:172 - applyDispatch(merge=true) catch-all treats every failure like a missing file and continues with generated JSON. If config/crew-dispatch.json exists but is invalid JSON, or parses without a rules array (mergeDispatch does existing.rules.map), dryRun=false then overwrites the captain file. Distinguish ENOENT from parse/shape errors; if the file exists but cannot be merged, refuse the write and surface the error.
  • ⚠️ src/quota.ts:45 - Missing-binary detection uses /ENOENT|not found|spawn/i on the error message. Node timeout/access failures are spawnSync … ETIMEDOUT/EACCES, so a 20s hang or permission error is reported as “quota-axi not found on PATH”. Classify missing via error.code === "ENOENT" (or equivalent) and keep other failures as quota-axi failed.
  • ⚠️ src/quota.ts:23 - readLiveQuota uses execFileSync with a 20s timeout. crew_route, crew_balance, and crew_suggest_primary therefore block the Pi event loop for the whole quota-axi run and ignore the tool AbortSignal (execute either omits signal or binds it as _signal). Switch to async execFile/spawn, honor signal, and keep the existing degraded-on-failure behavior.

🔧 Fix: Stale-Quota, Merge-Schutz und AbortSignal korrigiert
1 warning still open:

  • ⚠️ src/quota.ts:127 - readLiveQuota treats AbortSignal cancellation as a successful degraded quota-axi failure (early return at line 127 and catch at line 154). Reachable path: Pi aborts crew_route/crew_balance/crew_suggest_primary → exec is skipped or rejects with ABORT_ERR → degraded result → execute still runs routeTask/balance/suggestPrimary and returns a full offline recommendation. Abort is not a quota-axi outage; rethrow ABORT_ERR/AbortError (and throw on already-aborted at entry) so Pi records cancellation instead of feeding an offline answer after the user cancelled.

🔧 Fix: Quota-Abbruch als Cancellation statt Degraded behandeln
✅ Re-checked - no issues remain.

✅ **Test** - passed

✅ No issues found.

  • npm test (node built-in runner, tests/*.test.ts)
  • quota-axi --json live snapshot
  • node --experimental-strip-types /tmp/no-mistakes-evidence/01KZWZX6EYEXG8C1AFMG5TRSP2/e2e-tools.ts — classify/route/balance/dispatch/suggest against fixtures plus live quota
  • node --experimental-strip-types /tmp/no-mistakes-evidence/01KZWZX6EYEXG8C1AFMG5TRSP2/mock-pi-extension.ts — load index.ts, call crew_route/crew_balance/crew_apply_dispatch/crew_suggest_primary, slash /crew-route
  • Python semantic parse of .github/workflows/ci.yml (push/PR, setup-node 22, npm test)
  • Python semantic parse of package.json (pi-package keyword, pi.extensions, MIT)
  • validateDispatch against generated crew-dispatch.json and Firstmate docs/examples/crew-dispatch.json
  • CI-like npm install --no-fund --no-audit typebox (peer resolution) then npm test; worktree cleaned afterward
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

@thelad-dev
thelad-dev merged commit 6ebff5c into main Aug 13, 2026
1 check passed
@thelad-dev
thelad-dev deleted the fm/firstmate-crew-knowledge-mvp-20260812 branch August 13, 2026 12:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant