Skip to content

feat: add vendored hyper-jev skill and integration starter - #41

Merged
MrGTV-love merged 4 commits into
mainfrom
fm/fm-hyper-jev-skill
Oct 7, 2026
Merged

MrGTV-love merged 4 commits into
mainfrom
fm/fm-hyper-jev-skill

Conversation

@MrGTV-love

Copy link
Copy Markdown
Owner

Intent

This is an excellent skill that disler created for Jev: https://github.com/disler/ten-levels-of-jev/blob/main/.claude/skills/hyper-jev/SKILL.md

Jev work is best guided by a skill. We can defer if Kun has added one upstream to firstmate

Context: Main checked upstream kunchenguid/firstmate main: it has no Jev skill (only bin/fm-jev-mem-guard.* and docs/jev-guards.md), so there is nothing to defer to. Standing captain rules: use the reference he provides as-is and change it only where our codebase forces it; Jev calls go direct to TypeSafe (lower latency), never via OpenRouter; the TypeSafe key lives only in the primary home .env as TYPESAFE_API_KEY.

What Changed

  • Vendor disler’s hyper-jev skill with its cookbook, TypeScript client, thirty decision examples, offline tests, MIT license, and source provenance.
  • Add Firstmate-specific guidance requiring direct TypeSafe calls and resolving TYPESAFE_API_KEY only from the primary home .env, overriding conflicting upstream guidance.
  • Document the portable skill’s discovery exception, register its documentation audiences, and update changed-path test selection to skip vendored files while retaining the existing SKILL.md suite mapping.

Risk Assessment

🚨 High: The vendored skill contradicts the authoritative direct-TypeSafe and primary-home-only credential requirements, so it should not merge without resolving those conflicts; the remaining findings are bounded offline correctness and test-quality issues.

Testing

Live Claude skill discovery and overlay interpretation, isolated credential handling, bundled CLI execution, and adversarial changed-file selection passed; the audience check and upstream byte-contract comparison also passed. Initial socket-length and disabled-discovery setup issues were corrected before re-driving the scenarios. CLI transcripts and comparison evidence were retained, and disposable state was removed. No authenticated Jev API request was made; the offline demo is not evidence of live model accuracy.

  • Live validation: ✅ go - 6 of 6 scenarios driven live against the product
Scenario Result Live Evidence
Invoke /hyper-jev for firstmate production guidance and reject forbidden provider and credential proposals ✅ pass live Live project skill discovery transcript and Claude overlay response.
Request hyper-jev explicitly without a TypeSafe key and retain its resolved skill path ✅ pass live Named skill discovery and isolated credential boundary artifact.
Resolve a credential from an isolated primary-home .env without exporting or copying it ✅ pass live Named skill discovery and isolated credential boundary artifact.
Run the bundled offline demonstration and observe routing with explicitly mock accounting ✅ pass live Bundled offline support-routing demonstration artifact.
Start the bundled CLI without credentials and refuse a fabricated production decision ✅ pass live Bundled CLI refusal without credentials artifact.
Select changed-file checks for vendored skill updates without exempting unrelated source ✅ pass live Changed-file selector acceptance and adversarial refusal artifact.
Evidence: Live project skill discovery and complete Claude transcript

Source: Live project skill discovery and complete Claude transcript

$ tmux -L fm-lab -S .jev-live-lbyspat2/home/tmux/fm-lab capture-pane -p -J -S - -t primary
exit=0
{"type":"system","subtype":"init","cwd":"~/.no-mistakes/worktrees/32d18ed9638d/01M4BQ8TREJB9SH1V1QBQ3JBGA","session_id":"68c7c284-cb5e-4420-bcb3-e61d509b5025","tools":["Glob","Grep","Read","Skill"],"mcp_servers":[],"model":"claude-sonnet-5-5","permissionMode":"dontAsk","slash_commands":["afk","ahoy","bearings","hyper-jev","quiet","stow","updatefirstmate","deep-research","design","design-sync","dataviz","update-config","verify","debug","code-review","simplify","batch","fewer-permission-prompts","doctor","loop","schedule","claude-api","workflow-authoring","run","run-skill-generator","plugin-authoring","advisor","agents","auto-mode-setup","autocompact","clear","color","compact","config","output-style","context","effort","fast","focus","heapdump","init","mcp","import","model","__remote-workflow","workflow-launch-exec","reload-plugins","reload-skills","rename","ultrareview","security-review","usage-credits","extra-usage","usage","insights","recap","skill-doctor","goal","design-consent","design-revoke","list-agents","team-onboarding"],"terminal_slash_commands":["doctor","color","focus","reload-plugins"],"apiKeySource":"none","claude_code_version":"2.1.293","output_style":"default","agents":["claude","Explore","general-purpose","Plan","statusline-setup"],"skills":["afk","ahoy","bearings","hyper-jev","quiet","stow","updatefirstmate","deep-research","design","design-sync","dataviz","update-config","verify","debug","code-review","simplify","batch","fewer-permission-prompts","doctor","loop","schedule","claude-api","workflow-authoring","run","run-skill-generator","plugin-authoring"],"plugins":[{"name":"firstmate-calm","path":"~/.no-mistakes/worktrees/32d18ed9638d/01M4BQ8TREJB9SH1V1QBQ3JBGA/.claude/skills/firstmate-calm","source":"firstmate-calm@skills-dir","version":"1.0.0"},{"name":"cc-plugin-agents-md","path":"builtin","source":"cc-plugin-agents-md@builtin"},{"name":"cc-plugin-telemetry","path":"builtin","source":"cc-plugin-telemetry@builtin"},{"name":"cc-plugin-plugin-authoring","path":"builtin","source":"cc-plugin-plugin-authoring@builtin"}],"capabilities":["interrupt_receipt_v1","interrupt_cancel_queued_v1","interrupt_send_now_v1","msg_lifecycle_v1","request_marker_lists_v1","sdk_mcp_tools_list_changed","sdk_mcp_manifests","mcp_read_resource_v1","mcp_tool_ui_meta_v1","ui_surface_v1"],"analytics_disabled":false,"product_feedback_disabled":false,"uuid":"9e65c15f-a2fe-4250-a412-ef2362282b92","memory_paths":{"auto":"~/.claude/projects/-Users-charlesabrooker--no-mistakes-repos-32d18ed9638d-git/memory/"},"messaging_socket_path":"/tmp/cc-socks/63936.sock","fast_mode_state":"off","fast_mode_disabled_reason":"sdk_opt_in_required","per_turn_effort_active":true,"view_mode":"default"}
{"type":"system","subtype":"thinking_tokens","estimated_tokens":50,"estimated_tokens_delta":50,"session_id":"68c7c284-cb5e-4420-bcb3-e61d509b5025","uuid":"3705b48c-3201-4a44-9467-1077799d18cc"}
{"type":"system","subtype":"thinking_tokens","estimated_tokens":281,"estimated_tokens_delta":231,"session_id":"68c7c284-cb5e-4420-bcb3-e61d509b5025","uuid":"e9dd2450-3582-46ba-b569-16b50525eaa8"}
{"type":"assistant","message":{"model":"claude-sonnet-5-5","id":"msg_011CfoKg2LrHCZYhjrapNtYQ","type":"message","role":"assistant","content":[{"type":"thinking","thinking":"","signature":"CAQS2ggKEAgSGAI4AUIIdGhpbmtpbmcSDHyeGABWIWzZKCEcehoMCw/Uh9IgQ76xL3igIjAcX3k3VzOopzvSTNjHGMFyp4e6dqJAvdIL5Vq9toz10/f7iEXOOs2e6MuJEE94d6Eq9wdXO0hEqEKF4ciEURrDpZ7kekc0GPXPl1C2GnVHy0NgShsGGHniWa/QCFt6DJ5/Lxc0mKjQEbTREDuxyAXYRIzkr3z6geLId4nJ82/VexvRgnkvQOEhJAOvD4YOs273FPiekx6A5NsoYrToPPkb8NloCnx1RfgVYTOFENED8aE/RPio7dNC7GFMIAuXzKL/5KApI6sMFTGNbjzPRZyiB/U2xEFtA3y9NUw/0SEcOTQIW7YRz+M8Ve9lwcTUDYAllpuu+cGC3KLnDKWqLsYa90lTxAAWo9h5/XnsX2W5p4e0OWwPfJl83NcQDiFIiIU0QwdZcfzSIGcd/cX2A2/94MrIMn+CbEx3tBd3/+ZmPOmq+iFTlDRUWWP8YzlxNiXKXbtgmGIjv0bHNcOvJO7BWP+RJ7YP9sYiCGIKafXGMlj+WnX0KOcHAglVHJ24ZiWoi/x8vJfoNavVe7Enbm+MffLqgGWgTqTkrBuZkHxJjLoXDZe0Xry530ft1ocI/oVx/XajMedJhHy49nIjZKNcPegmhsVrYKsAI5eXB5Zi2IIfOyrOoWvgS/7VAHCLTCk442Vk49GW9S7vBrrdXxgeLiWqM/9RJPX3kmrVSnbHdewhoQW7k8WlSH7H9x72LT2bTn67tfqixcGbVkvvHxuPcoZzwecFd5N22I/k23P2QOZvlQmtmIrqyNxyTQ5UnroHQNbsecdP0AjAM6BugO9vNEUl6vERMeyoydu2E4xPLc8NkakZZz0c6Pq9cGvUYE4N/vsDZ2gO7nsKVhQagYppU+146CVAXUZX6eSoQ9xHfEQFL2SPR+BtSkBOTOE/B8sr3MNiJH03VyGvCJ1SqNDRgRnM3pY0jeIeiWjJ/PmhcRM7YaVlMYQUKzwpoIl0YwN+ChsGcXtjUD69Ze9ePbHTaFIpExpsNH6g+d32amrkFTGQbhGEDTscsErmpVFyDHIOhbyb3QciWXrHDGcrxdaDoEd7Eku6/x/FzChzOYhpRhV2RLMSIk1Lsq0kUcy6jhfyCgmmT6h1dsB7K7nLseGXqoCuxKBoQOo63wdCW5sDBVydYRqT5S5PQzXec9G3dIcnl4WMOKYNF5PQGmipJOTcLHxXdtx7olQUtpEHZ0MGzItA/NzI7v6AjxXyn/ypQ45wNZeAUgfpVx4Ofh1avxfwTdty8qN5bEeDckPIrqC2kIf8WQZLyAL8CJ9D9ErOwp8CFOlbxCY07ejJ8WeyhXJBId6HaJ9hNfl0QKZY/KGLBnH4kc3x9+cdCzvFVZL9CIWLCsU/6tI/wDxbC9/qN1YCfq5iMPhfysddwqrv7ffvEE9Vzxs7VcHungAbPsFNS3ToEdIJwklI1PVcGAE="}],"container":null,"stop_reason":null,"stop_sequence":null,"stop_details":null,"usage":{"input_tokens":2,"cache_creation_input_tokens":30876,"cache_read_input_tokens":3624,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":30876},"output_tokens":4,"service_tier":"standard","inference_geo":"not_available"},"input_transformations":[],"diagnostics":null,"context_management":null},"parent_tool_use_id":null,"session_id":"68c7c284-cb5e-4420-bcb3-e61d509b5025","uuid":"94149496-dc47-46fb-9e0d-954602aa4ddc","timestamp":"2026-10-07T18:07:39.676Z","request_id":"req_011CfoKg26DjmEhzTd58ABnq","thinking_duration_ms":1204}
{"type":"assistant","message":{"model":"claude-sonnet-5-5","id":"msg_011CfoKg2LrHCZYhjrapNtYQ","type":"message","role":"assistant","content":[{"type":"text","text":"I'll read the local guidance first, starting with the repo's own Jev overlay and then the bundled cookbook."}],"container":null,"stop_reason":null,"stop_sequence":null,"stop_details":null,"usage":{"input_tokens":2,"cache_creation_input_tokens":30876,"cache_read_input_tokens":3624,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":30876},"output_tokens":4,"service_tier":"standard","inference_geo":"not_available"},"input_transformations":[],"diagnostics":null,"context_management":null},"parent_tool_use_id":null,"session_id":"68c7c284-cb5e-4420-bcb3-e61d509b5025","uuid":"2b00f774-6576-4b7d-8e31-14d019a32733","timestamp":"2026-10-07T18:07:40.002Z","request_id":"req_011CfoKg26DjmEhzTd58ABnq"}
{"type":"assistant","message":{"model":"claude-sonnet-5-5","id":"msg_011CfoKg2LrHCZYhjrapNtYQ","type":"message","role":"assistant","content":[{"type":"tool_use","id":"toolu_01LEEpp5b9S7Dp9k9qw5kEWh","name":"Grep","input":{"pattern":"(?i)jev|TYPESAFE_API_KEY|OPENROUTER","glob":"!.claude/skills/hyper-jev/**","output_mode":"files_with_matches"},"caller":{"type":"direct"}}],"container":null,"stop_reason":null,"stop_sequence":null,"stop_details":null,"usage":{"input_tokens":2,"cache_creation_input_tokens":30876,"cache_read_input_tokens":3624,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":30876},"output_tokens":4,"service_tier":"standard","inference_geo":"not_available"},"input_transformations":[],"diagnostics":null,"context_management":null},"parent_tool_use_id":null,"session_id":"68c7c284-cb5e-4420-bcb3-e61d509b5025","uuid":"e4fce3ec-dc50-435b-97c5-2f8359447c95","timestamp":"2026-10-07T18:07:40.610Z","request_id":"req_011CfoKg26DjmEhzTd58ABnq","wire_tool_inputs":{"toolu_01LEEpp5b9S7Dp9k9qw5kEWh":{"pattern":"(?i)jev|TYPESAFE_API_KEY|OPENROUTER","glob":"!.claude/skills/hyper-jev/**","output_mode":"files_with_matches"}}}
{"type":"user","message":{"role":"user","content":[{"tool_use_id":"toolu_01LEEpp5b9S7Dp9k9qw5kEWh","type":"tool_result","content":"Found 103 files\n.jev-live-lbyspat2/task.txt\ndocs/documentation-audiences.json\n.agents/skills/hyper-jev/SOURCE.md\n.agents/skills/hyper-jev/FIRSTMATE.md\ntests/fm-worker-account.test.sh\ntests/fm-turnend-guard.test.sh\ntests/fm-test-run.test.sh\ntests/fm-skill-suggest.test.sh\ntests/fm-omp-jev-pipeline.test.sh\ntests/fm-model-index.test.sh\ntests/fm-jev-guardrail.test.sh\ntests/fm-jev-guardrail-home.test.sh\ntests/

... [69436 bytes truncated] ...

y is separate from provider choice, and you would need to add it deliberately.\n- **Fallback:** Route the ticket to the review path.\n- **Record:** Keep the failure and any raw payload alongside the decision, not a substitute answer.\n\n## Shape of the integration\n\n1. Define the decision with a small outcome set, such as category, blocked, and frustration, plus an explicit `review` outcome. Ask independent questions in one call.\n2. Keep the questions, thresholds, and pure policy function together in one named decision module. The starter's `src/decisions/support-routing.ts` is the model.\n3. Return `{ decision, result }` and keep the raw request, raw response, usage, and model ID. Don't keep only the derived decision.\n4. Keep arithmetic, date checks, and authorization in code. Jev is only an additional signal for bounded judgments.\n5. Test offline first with mocked HTTP for provider selection, malformed responses, raw-payload retention, and accounting. Run a live smoke test only when you authorize it, and report the provider and model actually observed.\n\nIf you want this built, firstmate project work goes to a worker. The change would also touch shared tracked material, so the worker would need `firstmate-coding-guidelines`. Tell me the delivery path and I'll dispatch it."}],"container":null,"stop_reason":null,"stop_sequence":null,"stop_details":null,"usage":{"input_tokens":2,"cache_creation_input_tokens":2909,"cache_read_input_tokens":39797,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":2909},"output_tokens":763,"service_tier":"standard","inference_geo":"not_available"},"input_transformations":[],"diagnostics":null,"context_management":null},"parent_tool_use_id":null,"session_id":"68c7c284-cb5e-4420-bcb3-e61d509b5025","uuid":"a9e77fed-a191-474b-8856-2033413207f2","timestamp":"2026-10-07T18:07:58.221Z","request_id":"req_011CfoKgjbZQgFQ9JogyAztL"}
{"duration_api_ms":20612,"stop_reason":"end_turn","session_id":"68c7c284-cb5e-4420-bcb3-e61d509b5025","total_cost_usd":0.20763320000000002,"usage":{"input_tokens":8,"cache_creation_input_tokens":39082,"cache_read_input_tokens":115696,"output_tokens":2815,"output_tokens_details":{"thinking_tokens":202},"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":39082,"ephemeral_5m_input_tokens":0},"inference_geo":"not_available","iterations":[{"input_tokens":2,"output_tokens":1567,"cache_read_input_tokens":39797,"cache_creation_input_tokens":2909,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":2909},"type":"message"}],"speed":"standard","fallback_credit":null},"modelUsage":{"claude-sonnet-5-5":{"inputTokens":8,"outputTokens":2815,"cacheReadInputTokens":115696,"cacheCreationInputTokens":39082,"webSearchRequests":0,"costUSD":0.20763320000000002,"contextWindow":1000000,"maxOutputTokens":128000,"thinkingTokens":202,"canonicalModel":"claude-sonnet-5-5","provider":"firstParty","costBasis":"list"}},"permission_denials":[],"terminal_reason":"completed","fast_mode_state":"off","fast_mode_disabled_reason":"sdk_opt_in_required","subagent_stats":{"spawned":0,"requested":{"background":0,"foreground":0,"unset":0},"started_in_background":0,"max_depth":0,"spawned_by_subagents":0,"completed":0,"failed":0,"killed":{"parent":0,"user":0,"system":0},"refused":{"depth_limit":0,"concurrency_limit":0,"budget":0},"by_type":{}},"safety_stops":0,"is_error":false,"num_turns":8,"subtype":"success","api_error_status":null,"result":"Captain, here is how to integrate Jev for production support triage in firstmate. I only read files. I changed nothing, made no calls, ran no commands, and did not touch any credentials.\n\n## Which guidance wins\n\nThe vendored upstream skill says to prefer `TYPESAFE_API_KEY`, fall back to `OPENROUTER_API_KEY`, and keep a service-local `.env`. This repo overrides that in `.agents/skills/hyper-jev/FIRSTMATE.md`. Its last line says the overlay wins in firstmate where the upstream text differs. Upstream's own `SOURCE.md` points to the overlay. Follow the overlay, not the upstream defaults.\n\n## Permitted provider and endpoint\n\n- **Provider:** TypeSafe direct, and nothing else.\n- **Endpoint:** `POST https://api.typesafe.ai/v1/systemone`. `bin/fm-typesafe-lib.sh` hard-codes it.\n- **Existing transport:** The shared helper `fm_typesafe_post` already provides a fixed five-second deadline and no retries. It prints only the HTTP code and keeps the key off argv. Use it rather than adding a second transport.\n- **Never-send policy:** `fm_typesafe_permitted` checks request text against the dispatch never-send list, which fits triage because support data can be sensitive. It withholds the request if a string matches or the list can't be inspected.\n\n## Where the key belongs and how to load it\n\n- **Location:** `TYPESAFE_API_KEY` goes in the primary home's `.env` and nowhere else.\n- **Loading:** Resolve it at call time with `fm_typesafe_key <home>` from `bin/fm-typesafe-lib.sh`. That reads `<home>/.env` through `fmx_env_get`.\n- **Process environment:** The library moves any inherited value into a private non-exported variable and unsets `TYPESAFE_API_KEY`, so children never inherit it.\n- **Never create** a service `.env`, an `.env.example` entry for the key, a secret-manager entry, or any other copy.\n- **Never print** the key, and keep Authorization headers out of audit records.\n\nThe bundled starter has its own `.env.example` and constructs its client from process environment. In firstmate, don't copy that pattern. Adapt the decision module so the key comes through `fm_typesafe_key`.\n\n## If only an OpenRouter key is available\n\nDon't use it for Jev in firstmate. The overlay says never select OpenRouter and never set `JEV_BACKEND` or `provider` to `openrouter`. With no `TYPESAFE_API_KEY`, treat Jev as unavailable. Per the upstream skill, missing credentials must not quietly turn into mock results for production decisions.\n\nFor triage, an unavailable Jev should send the ticket to the explicit human-review outcome. Only you can decide to add a TypeSafe key to the primary home `.env`, so that is the step to ask for. Upstream also notes that direct TypeSafe has not been live-verified as a deployment, so an authorized smoke test is still pending.\n\n## Should a failed call switch providers?\n\nNo. The overlay says never switch provider after a failed call. A failure means timeout, non-2xx, malformed response, or transport error (`000`). Handle each one as follows:\n\n- **Provider choice:** Stay on TypeSafe.\n- **Retries:** The shared helper does no retries. Any retry policy is separate from provider choice, and you would need to add it deliberately.\n- **Fallback:** Route the ticket to the review path.\n- **Record:** Keep the failure and any raw payload alongside the decision, not a substitute answer.\n\n## Shape of the integration\n\n1. Define the decision with a small outcome set, such as category, blocked, and frustration, plus an explicit `review` outcome. Ask independent questions in one call.\n2. Keep the questions, thresholds, and pure policy function together in one named decision module. The starter's `src/decisions/support-routing.ts` is the model.\n3. Return `{ decision, result }` and keep the raw request, raw response, usage, and model ID. Don't keep only the derived decision.\n4. Keep arithmetic, date checks, and authorization in code. Jev is only an additional signal for bounded judgments.\n5. Test offline first with mocked HTTP for provider selection, malformed responses, raw-payload retention, and accounting. Run a live smoke test only when you authorize it, and report the provider and model actually observed.\n\nIf you want this built, firstmate project work goes to a worker. The change would also touch shared tracked material, so the worker would need `firstmate-coding-guidelines`. Tell me the delivery path and I'll dispatch it.","ttft_ms":2542,"type":"result","duration_ms":21193,"uuid":"b9c6a5de-0f44-4ffb-8b52-9f79673383be","ttft_stream_ms":1338,"time_to_request_ms":125,"first_content_frame_ms":1338,"queued_turn_count":0,"result_index":0}
Evidence: Claude response applying firstmate provider and credential rules

Source: Claude response applying firstmate provider and credential rules

Captain, here is how to integrate Jev for production support triage in firstmate. I only read files. I changed nothing, made no calls, ran no commands, and did not touch any credentials.

## Which guidance wins

The vendored upstream skill says to prefer `TYPESAFE_API_KEY`, fall back to `OPENROUTER_API_KEY`, and keep a service-local `.env`. This repo overrides that in `.agents/skills/hyper-jev/FIRSTMATE.md`. Its last line says the overlay wins in firstmate where the upstream text differs. Upstream's own `SOURCE.md` points to the overlay. Follow the overlay, not the upstream defaults.

## Permitted provider and endpoint

- **Provider:** TypeSafe direct, and nothing else.
- **Endpoint:** `POST https://api.typesafe.ai/v1/systemone`. `bin/fm-typesafe-lib.sh` hard-codes it.
- **Existing transport:** The shared helper `fm_typesafe_post` already provides a fixed five-second deadline and no retries. It prints only the HTTP code and keeps the key off argv. Use it rather than adding a second transport.
- **Never-send policy:** `fm_typesafe_permitted` checks request text against the dispatch never-send list, which fits triage because support data can be sensitive. It withholds the request if a string matches or the list can't be inspected.

## Where the key belongs and how to load it

- **Location:** `TYPESAFE_API_KEY` goes in the primary home's `.env` and nowhere else.
- **Loading:** Resolve it at call time with `fm_typesafe_key <home>` from `bin/fm-typesafe-lib.sh`. That reads `<home>/.env` through `fmx_env_get`.
- **Process environment:** The library moves any inherited value into a private non-exported variable and unsets `TYPESAFE_API_KEY`, so children never inherit it.
- **Never create** a service `.env`, an `.env.example` entry for the key, a secret-manager entry, or any other copy.
- **Never print** the key, and keep Authorization headers out of audit records.

The bundled starter has its own `.env.example` and constructs its client from process environment. In firstmate, don't copy that pattern. Adapt the decision module so the key comes through `fm_typesafe_key`.

## If only an OpenRouter key is available

Don't use it for Jev in firstmate. The overlay says never select OpenRouter and never set `JEV_BACKEND` or `provider` to `openrouter`. With no `TYPESAFE_API_KEY`, treat Jev as unavailable. Per the upstream skill, missing credentials must not quietly turn into mock results for production decisions.

For triage, an unavailable Jev should send the ticket to the explicit human-review outcome. Only you can decide to add a TypeSafe key to the primary home `.env`, so that is the step to ask for. Upstream also notes that direct TypeSafe has not been live-verified as a deployment, so an authorized smoke test is still pending.

## Should a failed call switch providers?

No. The overlay says never switch provider after a failed call. A failure means timeout, non-2xx, malformed response, or transport error (`000`). Handle each one as follows:

- **Provider choice:** Stay on TypeSafe.
- **Retries:** The shared helper does no retries. Any retry policy is separate from provider choice, and you would need to add it deliberately.
- **Fallback:** Route the ticket to the review path.
- **Record:** Keep the failure and any raw payload alongside the decision, not a substitute answer.

## Shape of the integration

1. Define the decision with a small outcome set, such as category, blocked, and frustration, plus an explicit `review` outcome. Ask independent questions in one call.
2. Keep the questions, thresholds, and pure policy function together in one named decision module. The starter's `src/decisions/support-routing.ts` is the model.
3. Return `{ decision, result }` and keep the raw request, raw response, usage, and model ID. Don't keep only the derived decision.
4. Keep arithmetic, date checks, and authorization in code. Jev is only an additional signal for bounded judgments.
5. Test offline first with mocked HTTP for provider selection, malformed responses, raw-payload retention, and accounting. Run a live smoke test only when you authorize it, and report the provider and model actually observed.

If you want this built, firstmate project work goes to a worker. The change would also touch shared tracked material, so the worker would need `firstmate-coding-guidelines`. Tell me the delivery path and I'll dispatch it.
Evidence: Named skill discovery and isolated credential boundary

Source: Named skill discovery and isolated credential boundary

$ bin/fm-skill-suggest.sh --task-file ~/.no-mistakes/worktrees/32d18ed9638d/01M4BQ8TREJB9SH1V1QBQ3JBGA/.jev-live-lbyspat2/task.txt --format brief
exit=0

# Skill selection advice

Apply all existing mandatory explicit/named and safety triggers first, even if absent below.
This additive advice does not replace the skill index, authorize actions, or suppress any workflow.
Read relevant bodies through ordinary tools; reject unsuitable suggestions and add necessary skills.
Required named skill: hyper-jev - read ~/.no-mistakes/worktrees/32d18ed9638d/01M4BQ8TREJB9SH1V1QBQ3JBGA/.agents/skills/hyper-jev/SKILL.md.
No optional suggestion (off: TypeSafe key unavailable); continue ordinary selection.


$ bin/fm-skill-suggest.sh --task-file ~/.no-mistakes/worktrees/32d18ed9638d/01M4BQ8TREJB9SH1V1QBQ3JBGA/.jev-live-lbyspat2/task.txt --format brief
exit=0

# Skill selection advice

Apply all existing mandatory explicit/named and safety triggers first, even if absent below.
This additive advice does not replace the skill index, authorize actions, or suppress any workflow.
Read relevant bodies through ordinary tools; reject unsuitable suggestions and add necessary skills.
Required named skill: hyper-jev - read ~/.no-mistakes/worktrees/32d18ed9638d/01M4BQ8TREJB9SH1V1QBQ3JBGA/.agents/skills/hyper-jev/SKILL.md.
No optional suggestion (off: TypeSafe key unavailable); continue ordinary selection.


$ bash -c set -eu
. bin/fm-typesafe-lib.sh
fm_typesafe_key "$FM_HOME"
[ "$TYPESAFE_API_KEY_PRIVATE" = "disposable-typesafe-fixture-not-a-credential" ]
printf 'Credential resolved from isolated primary home .env: yes\n'
node -e 'if (process.env.TYPESAFE_API_KEY || process.env.TYPESAFE_API_KEY_PRIVATE) process.exit(1); console.log("Credential exported to child process: no")'

exit=0
Credential resolved from isolated primary home .env: yes
Credential exported to child process: no
Evidence: Bundled offline support-routing demonstration

Source: Bundled offline support-routing demonstration

$ node src/example.ts
exit=0
{
  "decision": {
    "route": "engineering",
    "reason": "Technical support"
  },
  "policyVersion": "support-routing-v1",
  "meta": {
    "provider": "mock",
    "requestedModel": "jev-1.13.0-mock",
    "resolvedModel": "jev-1.13.0-mock",
    "elapsedMs": 0,
    "attempts": 1,
    "cost": {
      "amount": 0,
      "source": "mock"
    }
  },
  "usage": {
    "input_tokens": 38,
    "output_tokens": 20
  },
  "totals": {
    "successfulLiveCalls": 0,
    "failedCalls": 0,
    "mockCalls": 1,
    "attemptsOnSuccessfulLiveCalls": 0,
    "inputTokens": 0,
    "outputTokens": 0,
    "reportedUsd": 0,
    "estimatedUsd": 0,
    "unknownCostCalls": 0
  }
}
Evidence: Bundled CLI refusal without credentials

Source: Bundled CLI refusal without credentials

$ node src/example.ts
exit=1
file://~/.no-mistakes/worktrees/32d18ed9638d/01M4BQ8TREJB9SH1V1QBQ3JBGA/.agents/skills/hyper-jev/templates/starter/src/core/client.ts:247
  throw new Error("No Jev credentials: set TYPESAFE_API_KEY or OPENROUTER_API_KEY, or explicitly select provider: mock / JEV_BACKEND=mock for offline use.");
        ^

Error: No Jev credentials: set TYPESAFE_API_KEY or OPENROUTER_API_KEY, or explicitly select provider: mock / JEV_BACKEND=mock for offline use.
    at selectProvider (file://~/.no-mistakes/worktrees/32d18ed9638d/01M4BQ8TREJB9SH1V1QBQ3JBGA/.agents/skills/hyper-jev/templates/starter/src/core/client.ts:247:9)
    at new JevClient (file://~/.no-mistakes/worktrees/32d18ed9638d/01M4BQ8TREJB9SH1V1QBQ3JBGA/.agents/skills/hyper-jev/templates/starter/src/core/client.ts:116:21)
    at file://~/.no-mistakes/worktrees/32d18ed9638d/01M4BQ8TREJB9SH1V1QBQ3JBGA/.agents/skills/hyper-jev/templates/starter/src/example.ts:6:16
    at ModuleJob.run (node:internal/modules/esm/module_job:447:25)
    at async node:internal/modules/esm/loader:646:26
    at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:101:5)

Node.js v26.4.0
Evidence: Changed-file selector acceptance and adversarial refusal

Source: Changed-file selector acceptance and adversarial refusal

$ bin/fm-test-run.sh --list --changed --base HEAD
exit=0
fm-test-run: no tests selected for changes vs HEAD (map is conservative; use --all for the complete suite)


$ bin/fm-test-run.sh --list --changed --base HEAD
exit=0
tests/fm-ask-user-authority.test.sh
tests/fm-test-run.test.sh


$ bin/fm-test-run.sh --list --changed --base HEAD
exit=2
fm-test-run: no changed-test mapping for source path: .agents/skills/not-hyper-jev/src/client.ts

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

⚠️ **Review** - 2 warnings
  • 🚨 .agents/skills/hyper-jev/SKILL.md:21 - The authoritative criterion says “Jev calls go direct to TypeSafe (lower latency), never via OpenRouter,” but the added instruction says “Prefer TYPESAFE_API_KEY, otherwise OPENROUTER_API_KEY.” In production, with only an OpenRouter key, the documented new JevClient() path selects OpenRouter and sends the complete decision state there; explicit provider and JEV_BACKEND overrides also select it even when TypeSafe credentials exist. Related sites under .agents/skills/hyper-jev/: templates/starter/src/core/client.ts:16 (provider union), :19 (endpoint), :24 (model), :29 (key), :113 (explicit provider acceptance), :132 (custom endpoint override), :240 (selection precedence), :242 (OpenRouter override), :246 (automatic selection), :194 (transport); cookbook/01-structure-and-setup.md:60 (fallback), :63 (override), :65 (guidance); cookbook/02-input-output.md:10 (endpoint), :40 (request adaptation); cookbook/04-client-operations.md:3 (interface), :13 (selection), :18 (fallback policy), :23 (example), :41 (option); cookbook/05-production.md:9 (provider guidance); cookbook/README.md:16 (transport); cookbook/use-cases/README.md:11 (live setup); templates/starter/README.md:16 and :18 (live setup); templates/starter/.env.example:3 (credential); templates/starter/tests/client.test.ts:58, :59, :89, :119, :131 and :148 (selection and transport expectations). This alternate live-provider component is forbidden, not required by the intent. Remove OpenRouter selection/transport and narrow live endpoint configuration to direct TypeSafe, updating its instructions and tests together; preserve the remaining upstream material.
  • 🚨 .agents/skills/hyper-jev/templates/starter/README.md:16 - The criterion says “the TypeSafe key lives only in the primary home .env as TYPESAFE_API_KEY,” but the added setup instructs a destination application to use a “private local .env” with node --env-file=.env src/example.ts. The setup cookbook explicitly creates a separate destination service, then gives the same service-local credential command. Following that path provisions a second credential location rather than using the primary home's existing key. Related sites under .agents/skills/hyper-jev/: cookbook/01-structure-and-setup.md:44–48 (destination creation), :55 (secret-manager provisioning), :67–73 (local environment-file setup); templates/starter/.env.example:2 (local key slot); SKILL.md:34 (initialization guidance lacks the required primary-home source); cookbook/use-cases/README.md:13 (credential loading guidance). Adapt these instructions to reference the primary home's existing .env without copying or provisioning the key in the destination service. The required primary-home credential boundary is currently absent from the skill.
  • ⚠️ .agents/skills/hyper-jev/templates/starter/src/core/mock.ts:147 - The offline backend silently loses valid proto keys because it constructs ordinary objects and assigns dynamic keys through bracket notation. For example, a question map parsed from {"proto":{"type":"noul","instructions":"Is this a greeting?"}} passes validation, but assignment changes the answers object's prototype; serialization and result cloning return answers: {} without rejecting the call. The same invariant fails at mock.ts:110–111 for Choice probabilities: an own proto criterion loses its probability. All question-type writes at mock.ts:149–151 must preserve own keys. Downstream affected sites are client.ts:177–182 (returns the mock result without response validation), levels/level09/wikiracing.ts:26 and :37 (dynamic titles and returned probabilities), and levels/level09/hierarchical-classify.ts:50 and :69–70 (dynamic category names and probability multiplication, which can yield NaN from the inherited value). Paths are relative to .agents/skills/hyper-jev/templates/starter/src/. Construct both dynamic maps with own-key-safe operations, such as Object.fromEntries or null-prototype objects, at the shared mock boundary.
  • ⚠️ .agents/skills/hyper-jev/templates/starter/tests/starter-regressions.test.ts:42 - Both assertions at lines 42–43 merely require the phrase diff_shape in instruction strings returned by buildReviewRubric. They still pass if judgePullRequest sends different state fields, stops sending these questions, or otherwise breaks the claimed alignment. This is the prohibited instruction-content-only test, not a check of the final emitted interface. Remove this wording-only case, or exercise judgePullRequest and inspect its actual outgoing request as an explicitly owned generated prompt/state contract. Update the corresponding claim in .agents/skills/hyper-jev/cookbook/use-cases/10-dynamic-questions.md:47.

🔧 Fix applied.
2 warnings still open:

  • ⚠️ .agents/skills/hyper-jev/templates/starter/src/core/mock.ts:147 - The offline backend silently loses valid proto keys because it constructs ordinary objects and assigns dynamic keys through bracket notation. For example, a question map parsed from {"proto":{"type":"noul","instructions":"Is this a greeting?"}} passes validation, but assignment changes the answers object's prototype; serialization and result cloning return answers: {} without rejecting the call. The same invariant fails at mock.ts:110–111 for Choice probabilities: an own proto criterion loses its probability. All question-type writes at mock.ts:149–151 must preserve own keys. Downstream affected sites are client.ts:177–182 (returns the mock result without response validation), levels/level09/wikiracing.ts:26 and :37 (dynamic titles and returned probabilities), and levels/level09/hierarchical-classify.ts:50 and :69–70 (dynamic category names and probability multiplication, which can yield NaN from the inherited value). Paths are relative to .agents/skills/hyper-jev/templates/starter/src/. Construct both dynamic maps with own-key-safe operations, such as Object.fromEntries or null-prototype objects, at the shared mock boundary.
  • ⚠️ .agents/skills/hyper-jev/templates/starter/tests/starter-regressions.test.ts:42 - Both assertions at lines 42–43 merely require the phrase diff_shape in instruction strings returned by buildReviewRubric. They still pass if judgePullRequest sends different state fields, stops sending these questions, or otherwise breaks the claimed alignment. This is the prohibited instruction-content-only test, not a check of the final emitted interface. Remove this wording-only case, or exercise judgePullRequest and inspect its actual outgoing request as an explicitly owned generated prompt/state contract. Update the corresponding claim in .agents/skills/hyper-jev/cookbook/use-cases/10-dynamic-questions.md:47.
✅ **Test** - passed

✅ No issues found.

  • Live validation: ✅ go - 6 of 6 scenarios driven live against the product
Scenario Result Live Evidence
Invoke /hyper-jev for firstmate production guidance and reject forbidden provider and credential proposals ✅ pass live Live project skill discovery transcript and Claude overlay response.
Request hyper-jev explicitly without a TypeSafe key and retain its resolved skill path ✅ pass live Named skill discovery and isolated credential boundary artifact.
Resolve a credential from an isolated primary-home .env without exporting or copying it ✅ pass live Named skill discovery and isolated credential boundary artifact.
Run the bundled offline demonstration and observe routing with explicitly mock accounting ✅ pass live Bundled offline support-routing demonstration artifact.
Start the bundled CLI without credentials and refuse a fabricated production decision ✅ pass live Bundled CLI refusal without credentials artifact.
Select changed-file checks for vendored skill updates without exempting unrelated source ✅ pass live Changed-file selector acceptance and adversarial refusal artifact.
  • node --version, tmux -V, claude --help, and omp --help confirmed available runtime and harness interfaces.
  • Compared all 89 vendored files, including LICENSE, byte-for-byte against the GitHub archive for upstream commit 777adaf47d37ae0553220d35b2f15b3a3a063305.
  • bin/fm-doc-audience-check.sh validated the documentation inventory and local links.
  • bin/fm-skill-suggest.sh --task-file &lt;disposable-task&gt; --format brief exercised named skill discovery with missing TypeSafe credentials and an OpenRouter-only environment.
  • Executed fm_typesafe_key &#34;$FM_HOME&#34; with a synthetic credential stored only in the disposable primary home's .env; verified resolution, absence from child-process environment, and no additional files.
  • Ran two read-only Claude primary sessions on a private, workspace-local tmux socket: one provenance-guided evaluation and one /hyper-jev invocation using normal project skill discovery. Captured the actual responses and stopped both servers.
  • JEV_BACKEND=mock node src/example.ts exercised the bundled CLI's documented offline demonstration.
  • node src/example.ts with both provider credentials and backend overrides unset verified that startup refuses missing credentials rather than inventing a decision.
  • bin/fm-test-run.sh --list --changed --base HEAD in a disposable repository exercised vendor-only changes, SKILL.md selection, and refusal of unrelated unmapped source.
  • bin/fm-lab-home.sh teardown &lt;disposable-home&gt; completed, followed by removal of all transient worktree fixtures.
🔧 **Document** - 3 issues found → auto-fixed ✅
  • ⚠️ .agents/skills/hyper-jev/SOURCE.md:14 - The provenance note says SOURCE.md is the only firstmate-added file besides LICENSE, but FIRSTMATE.md is now also present. Correcting this authoritative statement requires permission because the recorded decision permits only adding the top-of-file pointer and explicitly forbids other changes.
  • ⚠️ README.md:207 - The skill-layout owner claims every .agents/skills skill requires a live firstmate home and carries metadata.internal: true. The newly vendored hyper-jev skill is portable and lacks that metadata. CONTRIBUTING.md:57 repeats the stale claim. Qualify the README owner for this exception and reduce the contributor duplicate to a pointer, without modifying upstream files. These edits exceed the recorded exact-changes-only decision and require permission.
  • ℹ️ bin/fm-test-run.sh:139 - The runner header describes an unmapped bin/ path as the sole deliberately narrow changed-file selection case, but the added hyper-jev arm selects no suite for non-SKILL.md paths. The authoritative header should acknowledge this exception while retaining the preceding SKILL.md family-selection rule. A documentation-only correction exceeds the recorded exact-changes-only decision and requires permission.

🔧 Fix applied.
✅ Re-checked - no issues remain.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

@socket-security

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addednpm/​@​types/​node@​24.19.11001008196100
Addednpm/​typescript@​5.9.31001009010090

View full report

@MrGTV-love
MrGTV-love merged commit 5a2f323 into main Oct 7, 2026
21 checks passed
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