[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M7AJS2ADMXETND91YKDXK5ST":3,"skill-same:01M7AJS2ADMXETND91YKDXK5ST":49},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":19,"linkOnly":20,"markdownContent":21,"markdownBody":22,"frontMatter":23,"refName":25,"commitSha":26,"skillDirectory":27,"forksCount":28,"repositoryHtmlUrl":29,"repositoryHomepageUrl":30,"ownerHtmlUrl":31,"ownerBlogUrl":32,"ownerDescription":33,"updatedAt":34,"install":35,"resources":48},"01M7AJS2ADMXETND91YKDXK5ST","vibey-engine-adapters",null,"How vibey drives claudeloop, codexloop, and the local engines — gptossloop (the sovereign default), and the opt-in qwenloop and claudeloop-local — the engine adapter pattern, tiers, argv building, and the conformance suite.","the-vibey-project\u002Fvibey","the-vibey-project","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F329298758?v=4","01M7AJHGZ9722CTJ4JNQZVRH0Q","the vibey project","01M7AJHGZVMG2K7TGXQ6XFHVG3",5,"MIT","https:\u002F\u002Fgithub.com\u002Fthe-vibey-project\u002Fvibey\u002Fblob\u002Fdevelop\u002F.claude\u002Fskills\u002Fvibey-engine-adapters\u002FSKILL.md",[],[],"2026-11-15 14:19:17",false,"---\nname: vibey-engine-adapters\ndescription: How vibey drives claudeloop, codexloop, and the local engines — gptossloop (the sovereign default), and the opt-in qwenloop and claudeloop-local — the engine adapter pattern, tiers, argv building, and the conformance suite.\nallowed-tools: Read Grep\n---\n\n# vibey engine adapters\n\nVibey drives three autonomous session runners through five engine ids:\n`claudeloop` and `codexloop` (tier PAID) make up the default pool,\n`DEFAULT_DESCRIPTORS` (cursorloop and agyloop were retired by ADR-0078);\nthree local engines (tier LOCAL,\n`LOCAL_DESCRIPTORS`) join them, each behind its own switch (ADR-0064):\n`gptossloop` — the local runner on GPT-OSS 20B, the sovereign default, **on**\nunless `VIBEY_FEATURE_GPTOSSLOOP=0` \u002F `[features] gptossloop = false`; `qwenloop`\n— the same runner on a Qwen model (`qwen3:14b`), opt-in by\n`VIBEY_FEATURE_QWENLOOP=1` \u002F `[features] qwenloop = true` (ADR-0015); and\n`claudeloop-local` — the claudeloop binary run with a local backend profile\n(`--profile NAME`), opt-in by\n`VIBEY_FEATURE_CLAUDELOOP_LOCAL` \u002F `[features] claudeloop_local` (ADR-0038).\nUnder sub-doctrine 8.a local engines are **preferred first**: selection runs\nSWRR within the LOCAL tier and falls back to PAID only when no local engine is\neligible. gptossloop's model is also the sovereign DESIGN\u002FDECOMPOSE provider\n(`gptossloop_design.py`, `gptossloop_decompose.py`, ADR-0027), the default\n`--provider` (`--provider qwenloop` is read as gptossloop). The runners' source lives in this\nrepository under `src\u002Fvibey_runners\u002F{claude,codex,qwen,common}`\n(ADR-0021); vibey drives the installed binaries, not those packages' Python\nAPIs. Each has its own CLI surface, effort vocabulary,\nstate directory, and done marker. Vibey abstracts these differences via\n`EngineAdapter`, a `Protocol` defined in `application\u002Finterfaces\u002Fengines.py`\nand re-exported from `application\u002Fports.py`.\n\n## The adapter pattern\n\n`EngineAdapter` (read the real definition before relying on this summary —\nit's short):\n- `descriptor: EngineDescriptor` — a property, the engine's static facts\n- `async def preflight() -> PreflightResult` — runs `\u003Cengine> doctor`;\n  classifies auth + availability\n- `async def start(spec: RunSpec) -> RunHandle` — builds argv from\n  `descriptor.effort_projection` + isolation flags, spawns the runner,\n  returns a handle over its run directory\n- `def tail(handle: RunHandle) -> AsyncIterator[EngineEvent]` — streams the\n  runner's `events.jsonl`, translated into vibey's own event vocabulary\n  through `loop_events.py::LOOP_EVENT_MAP`. Only the runner's own turn\n  boundary maps to `TurnCompleted`, one per real turn, because the budget\n  brake counts it; chatter and stream deltas that echo a turn's text map\n  to `TranscriptRecorded`\n- `async def send_prompt(handle, text, *, now: bool) -> None` — writes the\n  runner's control-plane inbox\n- `async def stop(handle: RunHandle) -> StopSummary` — soft-stops the run;\n  collects `stop-summary.md` and the final snapshot\n- `async def snapshot(handle: RunHandle) -> SnapshotRef | None`\n- `def classify(raw: Mapping[str, object]) -> CapacityState` — maps a raw vendor\n  error shape to `Available | WindowExhausted | CreditsExhausted | AuthenticationFailed`\n- `def attribute(exit_code: int, tail: str) -> FailureClass` — attributes a dead\n  process to a `FailureClass` (`capacity`, `engine`, `work`, `vibey`)\n\nAn engine session never inherits the worker's environment: every spawn (the run,\n`--version`, `doctor`, `--help`) builds it through\n`LoopProcessAdapter.environment`, an `EngineEnvironmentPolicy`\n(`infrastructure\u002Fengines\u002Fengine_environment.py`) over the one builder,\n`infrastructure\u002Fprocess\u002Fchild_environment.py::ChildEnvironment`. It is an\nallow-list: the system basics, the descriptor's `env_passthrough` and `auth_env`,\nand the project's `engine_environment` additions, declared in vibey.toml's\n`[engine_environment]` (copied into the record by `vibey new`) or the\n`VibeyProject` spec's `engineEnvironment` — never hand-edited into the record.\n`VIBEY_*`, `PG*` and anything DSN- or password-shaped can never be on it, so\n`VIBEY_PG_URL` never reaches a model-driven process; a descriptor or overlay that\ntries is refused when the adapter is built. The worker's startup preflight and\n`vibey doctor --record` probe with the project's policy, so a declared credential\nreaches the auth check too. A new engine declares what its runner and vendor CLI\nread in `env_passthrough`; do not add a spawn path that passes `env=` itself.\nvibey's own git calls (`infrastructure\u002Fgit\u002Fclean_env.py`) and the `az` adapter\nbuild their environments the same way, never from a copy.\n`LoopProcessAdapter.env_overlay` is laid over that last (run and preflight alike) —\nhow gptossloop gets `GPTOSSLOOP_BASE_URL`\u002F`GPTOSSLOOP_MODEL`, and qwenloop only\n`QWENLOOP_BASE_URL` (never a model), from the one setting `VIBEY_OLLAMA_URL`\n(`local_engines.py::LocalEndpointEnvironment`).\nPreflight runs `\u003Cbinary> doctor` plus `descriptor.doctor_args`\n(claudeloop-local: `--profile NAME`).\n\nPreflight's `--version` and `doctor` probes each lead a process group of their own.\nOn a timeout or a cancellation, `infrastructure\u002Fprocess\u002Freaper.py::ProcessReaper`\nkills the whole group and reaps it within `LoopProcessAdapter.kill_grace_seconds`,\nlogging `engine_process_not_reaped` if a descendant that left the group still holds\nthe pipes. The gate runner and the skills-context compiler use the same reaper.\nNever hand-roll a kill followed by an unbounded `process.wait()` (#283, ADR-0017).\nThe run's environment strips the interpreter's prefix only when it is a venv\n(`infrastructure\u002Fprocess\u002Fpython_env.py::OrchestratorPythonEnv`, shared with the gate\nrunner), so a system-Python install keeps `\u002Fusr\u002Fbin`.\n\n`start()` internally calls `infrastructure\u002Fengines\u002Fargv.py::build_argv()` —\nthat's a plain function, not an adapter method; it takes both the descriptor\nand the `RunSpec` (`build_argv(descriptor, spec)`), not just the spec.\n\nSee `application\u002Finterfaces\u002Fengines.py::EngineAdapter` and\n`infrastructure\u002Fengines\u002Fscripted.py::ScriptedEngine` (the fake runner used in\ntests). `infrastructure\u002Fengines\u002Floop_process_adapter.py::LoopProcessAdapter`\nis the production adapter (it supersedes `ClaudeLoopProcess`): it spawns the\nloop process, streams `events.jsonl`, detects `done_marker`, treats exit code 75\nas wind-down, and classifies capacity through `classify.py` — one class driven\nby descriptors, not one class per engine.\n\nEngine choice for engine-driven BUILD jobs goes through\n`SelectingEngineProvider → application\u002Fengine_selector.py::EngineSelector`\n(SWRR over `domain\u002Frotation.py`), wired in `bootstrap.py`. The selector builds a\ncandidate per eligible engine and `domain\u002Frotation.py::preferred_tier` offers SWRR\nonly the first tier in `TIER_PREFERENCE` (LOCAL, PAID) holding a candidate that\ncan win. The provider passes its pool (adapters ∩ `--engines`) as the allow-list,\nand refreshes every enabled local engine's health from its `doctor` before each\nselection. Selection requires populated `engine_health` rows, so an engine with\nno recorded conformance is never selected.\n\nHybrid dispatch (ADR-0079, sub-doctrine 8.k) sits on top: `[engines] mode` is\n`singleton` (exactly the above), `hybrid` or `auto` (the default: `hybrid` only from a\ncurrent `EngineDispatchMeasured` ledger event, else `singleton`). Under `hybrid`,\n`domain\u002Fengine_dispatch.py::EngineDispatcher` plans over the same candidates: local\nengines fill their `[engines.slots]` first (1 local, 2 paid by default); with every\neligible local slot occupied a job is held (`SlotHeld` → `CapacityDeferred`, recorded once\nper attempt as `EngineSlotWaitStarted`) until it has waited `overflow_after_seconds`, then\na paid engine with a free slot takes it as overflow — reserved under the project row's\nlock against `paid_daily_cap`, counted from `EngineOverflowSelected` events for the UTC\nday. Slots in use are the job table's unexpired leases per `assigned_engine`. The provider\ntakes `dispatch=` (`application\u002Fengine_dispatch_service.py::EngineDispatchService`, wired\nby `bootstrap._engine_dispatch`); `dispatch=None` is today's selection, unconditionally.\nCounts reach the domain as data; never read the queue or a clock from `domain\u002F`.\n\nBefore `build.implement` seeds a fresh run, it can ask the `vibey-skills` CLI for\na skills-context packet (`infrastructure\u002Fskills_context.py::VibeySkillsContextCompiler`,\nmodes `off`\u002F`shadow`\u002F`inject`, budget 1,000–32,000 with a 6,000 default;\nADR-0031). The packet is recorded as a `vibey_skills_context_packet` artifact.\n\n## Engine descriptors\n\n`infrastructure\u002Fengines\u002Fdescriptors.py` defines `CLAUDELOOP`, `CODEXLOOP`,\n`GPTOSSLOOP`, `QWENLOOP`, `CLAUDELOOP_LOCAL` — one\n`EngineDescriptor` per engine. claudeloop-local's is *built* from `[engines.claudeloop_local]`\n(`profile`, `context_window`, `structured_verdict`) by\n`ClaudeloopLocalDescriptors.build()`; the constant is the default profile `local`.\n`GPTOSSLOOP` is `QWENLOOP` with its own id, binary and `GPTOSSLOOP_*`\npassthrough: one runner, whose run layout (`.qwenloop\u002Fruns\u002F`), done marker and\nevents both engines share.\n`DEFAULT_DESCRIPTORS` is the default pool of two, `LOCAL_DESCRIPTORS` the three\nlocal ones, `ALL_DESCRIPTORS` all five, and `BY_ENGINE_ID` maps every\n`EngineId`. The worker\nadds adapters for the local engines that are switched on through\n`local_engines.py::LocalEngineSettings` — the one resolver bootstrap, `worker`,\n`work` and `doctor` share.\n\nEach descriptor (`domain\u002Fengine.py::EngineDescriptor`) declares:\n- `engine_id`, `binary` — the executable name (e.g., `\"claudeloop\"`), `min_version`\n- `state_dir` — where runs are stored (e.g., `\".claudeloop\u002F\"`)\n- `done_marker` — the text signaling completion (e.g., `\"CLAUDELOOP_TASK_FULLY_COMPLETE\"`)\n- `capabilities` — which features it supports (`savepoints`, `unwind`, etc.). A\n  claim must agree with the facts below (`test_descriptors.py`): `mid_run_prompt`\n  exactly where `controls.prompt` is declared, `attachments` only where `images`\n  or `paste_images` is proven `True`, `web_search` only where the runner's `run`\n  takes `--web-search`\n- `effort_projection` — how vibey's 5-level ladder (`TRIVIAL, LOW, STANDARD, HIGH, MAX`)\n  maps to the engine's native flags\n- `auth_env` — environment variables that must be set (empty for gptossloop and qwenloop)\n- `env_passthrough` — the variables the engine's runner and vendor CLI read, passed\n  to its sessions (a trailing `*` names a prefix); nothing else reaches a session\n  unless the project declares it\n- `session_verb`, `isolation_flags` (per `IsolationLevel`)\n- `cost_per_mtok_in`\u002F`cost_per_mtok_out`, `context_window`, `base_weight` (rotation weight)\n- `tier` (`EngineTier.PAID` default, `LOCAL` for gptossloop, qwenloop and claudeloop-local) and\n  `doctor_args` (extra `doctor` arguments; claudeloop-local: `--profile NAME`)\n- `supports_cwd_flag` (default `True`; codexloop: `False`) and `plan_flag`\n  (default `None` = positional plan path; no current engine sets one)\n- `affordances` — `EngineAffordances`: `images`, `files`, `paste_text`,\n  `paste_images`, `plugins` (`PluginSystem`) and `mcp`, each `True`, `False` or\n  `None` (unknown, the default). `evidence` names, for every value that is set,\n  where the runner's own code shows it; a set value without evidence fails a\n  test. Never set one from memory or a vendor's marketing\n- `controls` — `EngineControls`: `stop`, `wind_down` and `prompt` as argv\n  templates after the binary (`{run_id}`, `{cwd}`, `{text}`), `None` where the\n  runner has no such verb or does not act on it. Tests read every template against\n  the runner's own Typer app the way click parses it\n- `events` — `EventLog`: the `path` template of its `events.jsonl` and its\n  `envelope` (`EventEnvelope`: `type`, `event_type+payload`, or `event_type`)\n\n**Effort projection example** (claudeloop, as in `descriptors.py`):\n\n```python\neffort_projection={\n    Effort.TRIVIAL: EngineInvocation((\"--preset\", \"low\", \"--effort\", \"low\"), achieved=Effort.TRIVIAL),\n    Effort.LOW: EngineInvocation((\"--preset\", \"low\", \"--effort\", \"medium\"), achieved=Effort.LOW),\n    Effort.STANDARD: EngineInvocation((\"--preset\", \"medium\", \"--effort\", \"high\"), achieved=Effort.STANDARD),\n    Effort.HIGH: EngineInvocation((\"--preset\", \"high\", \"--effort\", \"high\"), achieved=Effort.HIGH),\n    Effort.MAX: EngineInvocation((\"--preset\", \"high\", \"--effort\", \"max\"), achieved=Effort.MAX),\n}\n```\n\ngptossloop and qwenloop project effort onto `--max-turns` (8, 16, 40, 64, 96).\nclaudeloop-local passes `--profile NAME --preset low|low|medium|high|high` and\nnever `--effort`; HIGH and MAX report `achieved=STANDARD`, its honest ceiling.\n\nIf an engine **saturates**, the descriptor sets `achieved` to the tier it\nactually delivers. codexloop is the extreme case: its `run` has no effort flag,\nso every level projects to empty argv with `achieved=Effort.STANDARD`.\n`domain\u002Frotation.py::fidelity_factor(descriptor, requested)` computes the\n`Candidate.fidelity_factor` that scales the effective weight of engines that\nsaturate below the requested effort; `application\u002Fengine_selector.py` applies\nit.\n\nSee ADR-0006 (normalized effort ladder).\n\n## argv building\n\n`infrastructure\u002Fengines\u002Fargv.py::build_argv(descriptor, spec)` takes an\n`EngineDescriptor` and a `RunSpec` (fields: `run_id`, `worktree_path`,\n`prompt`, `effort`, `isolation`, optional `session_id` to resume) and\nproduces the command line — read the real function, it is short. As of\n2026-09-15 it emits, in order:\n\n1. `\u003Cbinary> run`, or `\u003Cbinary> resume \u003Csession_id>` when `spec.session_id` is set.\n2. For `run` only: the plan path `\u003Cworktree>\u002F.vibey\u002Fplans\u002F\u003Crun_id>.md`, prefixed\n   by `descriptor.plan_flag` when an engine sets one,\n   then `--run-id \u003Crun_id>` (so the adapter finds the run directory the process\n   writes to).\n3. `descriptor.invoke(effort).argv`.\n4. `descriptor.isolation_flags.get(isolation, ())`.\n5. `--cwd \u003Cworktree_path>`, only when `descriptor.supports_cwd_flag` (codexloop:\n   `False`).\n\n30 golden files under `tests\u002Finfrastructure\u002Fengines\u002Fgolden\u002F` (5 engines × 6\nefforts, ULTRA included; `test_argv.py` parametrizes over `ALL_DESCRIPTORS`) capture the\nexpected argv for each combination — the source of truth for the exact current\nshape.\n\n`argv.py::RUN_ARGV_TEMPLATE` (`RunArgvTemplate`) is `build_argv`'s `run` line with\nits per-run values as placeholders: `{binary}`, `run`, `{plan_flag?}` (only with a\n`plan_flag`), `{plan}`, `--run-id`, `{run_id}`, `{effort_argv...}`, and `--cwd\n{cwd}` when `supports_cwd_flag`. It is what `vibey loops` publishes for a caller\nthat starts a runner itself, such as the VS Code extension. Tests compare it with\n`build_argv` for every engine and effort, and read it, filled in at every effort\nand isolation level, against the runner's own `run` definition.\n\n## What `vibey loops` reports\n\n`vibey loops [--json]` (`application\u002Floops.py::LoopCatalog`, `cli\u002Floops.py`) lists\nthe two loops of sub-doctrine 8.c, each engine under the loop its tier puts it in,\nwith every effort's argv, achieved effort and model, and the descriptor's run\ntemplate, `affordances`, `controls`, `events` and env names (names only). It reads\nthe local switches (and whether each is `on_by_default`) and each local runner's\nmodel through `local_engines.py`, the resolvers\n`vibey doctor` reads. An engine canon 8.b repeals (`REPEALED_FROM_LOOPS`; empty\nsince OpenCode's engine was deleted) is listed with `repealed: true` and left out of\nevery by-effort view. The document for one\nfixed environment is committed as `tests\u002Fcli\u002Fgolden\u002Fvibey-loops.json`: after\nchanging a descriptor, regenerate it with\n`VIBEY_UPDATE_GOLDENS=1 uv run pytest tests\u002Fcli\u002Ftest_loops_cli.py -k golden` and\ncommit it with the change.\n\n## Capacity classification\n\n`infrastructure\u002Fengines\u002Fclassify.py::classify_capacity(engine_id, raw)` dispatches\nto one private classifier per engine (claudeloop-local shares claudeloop's) and\nmaps vendor-specific error shapes to vibey's `CapacityState`. claudeloop writes\nits capacity as the class *name* (`\"capacity\": \"CreditsExhausted\"`); both that and\nthe `{\"state\": ...}` mapping are read, and `BackendMisconfigured` maps to\n`AuthenticationFailed` (terminal, never credits). Exit 78 (EX_CONFIG,\n`EXIT_CODE_BACKEND_MISCONFIGURED`) is attributed to ENGINE, and an incomplete run\nthat exited 78 parks its BUILD job on an `engine_misconfigured` gate\n(`RunOutcome.misconfiguration_gate`) instead of retrying:\n\n```python\nAvailable | WindowExhausted | CreditsExhausted | AuthenticationFailed\n```\n\n**The critical distinction:** `WindowExhausted` has a `resets_at` deadline;\n`CreditsExhausted` does not. A window exhaustion is waitable; credits\nexhaustion requires a human top-up.\n\nEach engine's classifier pattern is versioned in `CREDITS_FIXTURES`,\n`WINDOW_FIXTURES`, `AUTH_FIXTURES`, and `AVAILABLE_FIXTURES` — shared between\nthe classifier's own tests and the conformance suite.\n\n**Note:** these are synthesized fixture payloads, not captured real vendor\nerrors. If you get access to real `*loop` binaries or real captured error\npayloads, this is the first thing to replace.\n\n## The conformance suite\n\n`application\u002Fconformance.py::run_conformance()` runs 9 named checks per\nengine (grep the file for the check-name strings if this list drifts):\n`binary` (installed + version), `flags` (`run --help` exposes what the\ndescriptor claims), `state_dir`, `run_dir_shape` (a real run produces\n`meta.json`\u002F`events.jsonl`\u002F`snapshots\u002Flatest.json` — this one races a real\nsubprocess's own startup time, not just an instant file check; read the\nfunction if you're touching it), `snapshot_schema`, `capacity_map`,\n`done_marker`, `control_plane`, `structured_verdict`.\n\nA failing conformance check marks that engine **ineligible** rather than\nletting it fail mid-cycle.\n\n```bash\nvibey doctor --conformance --record\n```\n\n`--record` persists the preflight and conformance result to `engine_health`.\nWithout a recorded pass the worker warns and never selects the engine for\nengine-driven jobs.\n\nLive runs of the suite are split in two modes (ADR-0030): `tests\u002Flive\u002F` with\n`@pytest.mark.live` runs conformance and rotation against `ScriptedEngine`\nand scripted stand-in binaries, with no model calls; `@pytest.mark.paid` spawns real binaries\nagainst real models and is excluded by default.\n\nSee ADR-0001 (orchestrate, do not reimplement).\n\n## When to read this skill\n\nBefore:\n- Adding a new engine.\n- Changing effort mappings.\n- Changing what an engine declares it can take, control or emit (`affordances`,\n  `controls`, `events`), or anything `vibey loops` reports.\n- Debugging why rotation is skipping an engine.\n- Updating capacity classification patterns after a vendor API change.\n","# vibey engine adapters\n\nVibey drives three autonomous session runners through five engine ids:\n`claudeloop` and `codexloop` (tier PAID) make up the default pool,\n`DEFAULT_DESCRIPTORS` (cursorloop and agyloop were retired by ADR-0078);\nthree local engines (tier LOCAL,\n`LOCAL_DESCRIPTORS`) join them, each behind its own switch (ADR-0064):\n`gptossloop` — the local runner on GPT-OSS 20B, the sovereign default, **on**\nunless `VIBEY_FEATURE_GPTOSSLOOP=0` \u002F `[features] gptossloop = false`; `qwenloop`\n— the same runner on a Qwen model (`qwen3:14b`), opt-in by\n`VIBEY_FEATURE_QWENLOOP=1` \u002F `[features] qwenloop = true` (ADR-0015); and\n`claudeloop-local` — the claudeloop binary run with a local backend profile\n(`--profile NAME`), opt-in by\n`VIBEY_FEATURE_CLAUDELOOP_LOCAL` \u002F `[features] claudeloop_local` (ADR-0038).\nUnder sub-doctrine 8.a local engines are **preferred first**: selection runs\nSWRR within the LOCAL tier and falls back to PAID only when no local engine is\neligible. gptossloop's model is also the sovereign DESIGN\u002FDECOMPOSE provider\n(`gptossloop_design.py`, `gptossloop_decompose.py`, ADR-0027), the default\n`--provider` (`--provider qwenloop` is read as gptossloop). The runners' source lives in this\nrepository under `src\u002Fvibey_runners\u002F{claude,codex,qwen,common}`\n(ADR-0021); vibey drives the installed binaries, not those packages' Python\nAPIs. Each has its own CLI surface, effort vocabulary,\nstate directory, and done marker. Vibey abstracts these differences via\n`EngineAdapter`, a `Protocol` defined in `application\u002Finterfaces\u002Fengines.py`\nand re-exported from `application\u002Fports.py`.\n\n## The adapter pattern\n\n`EngineAdapter` (read the real definition before relying on this summary —\nit's short):\n- `descriptor: EngineDescriptor` — a property, the engine's static facts\n- `async def preflight() -> PreflightResult` — runs `\u003Cengine> doctor`;\n  classifies auth + availability\n- `async def start(spec: RunSpec) -> RunHandle` — builds argv from\n  `descriptor.effort_projection` + isolation flags, spawns the runner,\n  returns a handle over its run directory\n- `def tail(handle: RunHandle) -> AsyncIterator[EngineEvent]` — streams the\n  runner's `events.jsonl`, translated into vibey's own event vocabulary\n  through `loop_events.py::LOOP_EVENT_MAP`. Only the runner's own turn\n  boundary maps to `TurnCompleted`, one per real turn, because the budget\n  brake counts it; chatter and stream deltas that echo a turn's text map\n  to `TranscriptRecorded`\n- `async def send_prompt(handle, text, *, now: bool) -> None` — writes the\n  runner's control-plane inbox\n- `async def stop(handle: RunHandle) -> StopSummary` — soft-stops the run;\n  collects `stop-summary.md` and the final snapshot\n- `async def snapshot(handle: RunHandle) -> SnapshotRef | None`\n- `def classify(raw: Mapping[str, object]) -> CapacityState` — maps a raw vendor\n  error shape to `Available | WindowExhausted | CreditsExhausted | AuthenticationFailed`\n- `def attribute(exit_code: int, tail: str) -> FailureClass` — attributes a dead\n  process to a `FailureClass` (`capacity`, `engine`, `work`, `vibey`)\n\nAn engine session never inherits the worker's environment: every spawn (the run,\n`--version`, `doctor`, `--help`) builds it through\n`LoopProcessAdapter.environment`, an `EngineEnvironmentPolicy`\n(`infrastructure\u002Fengines\u002Fengine_environment.py`) over the one builder,\n`infrastructure\u002Fprocess\u002Fchild_environment.py::ChildEnvironment`. It is an\nallow-list: the system basics, the descriptor's `env_passthrough` and `auth_env`,\nand the project's `engine_environment` additions, declared in vibey.toml's\n`[engine_environment]` (copied into the record by `vibey new`) or the\n`VibeyProject` spec's `engineEnvironment` — never hand-edited into the record.\n`VIBEY_*`, `PG*` and anything DSN- or password-shaped can never be on it, so\n`VIBEY_PG_URL` never reaches a model-driven process; a descriptor or overlay that\ntries is refused when the adapter is built. The worker's startup preflight and\n`vibey doctor --record` probe with the project's policy, so a declared credential\nreaches the auth check too. A new engine declares what its runner and vendor CLI\nread in `env_passthrough`; do not add a spawn path that passes `env=` itself.\nvibey's own git calls (`infrastructure\u002Fgit\u002Fclean_env.py`) and the `az` adapter\nbuild their environments the same way, never from a copy.\n`LoopProcessAdapter.env_overlay` is laid over that last (run and preflight alike) —\nhow gptossloop gets `GPTOSSLOOP_BASE_URL`\u002F`GPTOSSLOOP_MODEL`, and qwenloop only\n`QWENLOOP_BASE_URL` (never a model), from the one setting `VIBEY_OLLAMA_URL`\n(`local_engines.py::LocalEndpointEnvironment`).\nPreflight runs `\u003Cbinary> doctor` plus `descriptor.doctor_args`\n(claudeloop-local: `--profile NAME`).\n\nPreflight's `--version` and `doctor` probes each lead a process group of their own.\nOn a timeout or a cancellation, `infrastructure\u002Fprocess\u002Freaper.py::ProcessReaper`\nkills the whole group and reaps it within `LoopProcessAdapter.kill_grace_seconds`,\nlogging `engine_process_not_reaped` if a descendant that left the group still holds\nthe pipes. The gate runner and the skills-context compiler use the same reaper.\nNever hand-roll a kill followed by an unbounded `process.wait()` (#283, ADR-0017).\nThe run's environment strips the interpreter's prefix only when it is a venv\n(`infrastructure\u002Fprocess\u002Fpython_env.py::OrchestratorPythonEnv`, shared with the gate\nrunner), so a system-Python install keeps `\u002Fusr\u002Fbin`.\n\n`start()` internally calls `infrastructure\u002Fengines\u002Fargv.py::build_argv()` —\nthat's a plain function, not an adapter method; it takes both the descriptor\nand the `RunSpec` (`build_argv(descriptor, spec)`), not just the spec.\n\nSee `application\u002Finterfaces\u002Fengines.py::EngineAdapter` and\n`infrastructure\u002Fengines\u002Fscripted.py::ScriptedEngine` (the fake runner used in\ntests). `infrastructure\u002Fengines\u002Floop_process_adapter.py::LoopProcessAdapter`\nis the production adapter (it supersedes `ClaudeLoopProcess`): it spawns the\nloop process, streams `events.jsonl`, detects `done_marker`, treats exit code 75\nas wind-down, and classifies capacity through `classify.py` — one class driven\nby descriptors, not one class per engine.\n\nEngine choice for engine-driven BUILD jobs goes through\n`SelectingEngineProvider → application\u002Fengine_selector.py::EngineSelector`\n(SWRR over `domain\u002Frotation.py`), wired in `bootstrap.py`. The selector builds a\ncandidate per eligible engine and `domain\u002Frotation.py::preferred_tier` offers SWRR\nonly the first tier in `TIER_PREFERENCE` (LOCAL, PAID) holding a candidate that\ncan win. The provider passes its pool (adapters ∩ `--engines`) as the allow-list,\nand refreshes every enabled local engine's health from its `doctor` before each\nselection. Selection requires populated `engine_health` rows, so an engine with\nno recorded conformance is never selected.\n\nHybrid dispatch (ADR-0079, sub-doctrine 8.k) sits on top: `[engines] mode` is\n`singleton` (exactly the above), `hybrid` or `auto` (the default: `hybrid` only from a\ncurrent `EngineDispatchMeasured` ledger event, else `singleton`). Under `hybrid`,\n`domain\u002Fengine_dispatch.py::EngineDispatcher` plans over the same candidates: local\nengines fill their `[engines.slots]` first (1 local, 2 paid by default); with every\neligible local slot occupied a job is held (`SlotHeld` → `CapacityDeferred`, recorded once\nper attempt as `EngineSlotWaitStarted`) until it has waited `overflow_after_seconds`, then\na paid engine with a free slot takes it as overflow — reserved under the project row's\nlock against `paid_daily_cap`, counted from `EngineOverflowSelected` events for the UTC\nday. Slots in use are the job table's unexpired leases per `assigned_engine`. The provider\ntakes `dispatch=` (`application\u002Fengine_dispatch_service.py::EngineDispatchService`, wired\nby `bootstrap._engine_dispatch`); `dispatch=None` is today's selection, unconditionally.\nCounts reach the domain as data; never read the queue or a clock from `domain\u002F`.\n\nBefore `build.implement` seeds a fresh run, it can ask the `vibey-skills` CLI for\na skills-context packet (`infrastructure\u002Fskills_context.py::VibeySkillsContextCompiler`,\nmodes `off`\u002F`shadow`\u002F`inject`, budget 1,000–32,000 with a 6,000 default;\nADR-0031). The packet is recorded as a `vibey_skills_context_packet` artifact.\n\n## Engine descriptors\n\n`infrastructure\u002Fengines\u002Fdescriptors.py` defines `CLAUDELOOP`, `CODEXLOOP`,\n`GPTOSSLOOP`, `QWENLOOP`, `CLAUDELOOP_LOCAL` — one\n`EngineDescriptor` per engine. claudeloop-local's is *built* from `[engines.claudeloop_local]`\n(`profile`, `context_window`, `structured_verdict`) by\n`ClaudeloopLocalDescriptors.build()`; the constant is the default profile `local`.\n`GPTOSSLOOP` is `QWENLOOP` with its own id, binary and `GPTOSSLOOP_*`\npassthrough: one runner, whose run layout (`.qwenloop\u002Fruns\u002F`), done marker and\nevents both engines share.\n`DEFAULT_DESCRIPTORS` is the default pool of two, `LOCAL_DESCRIPTORS` the three\nlocal ones, `ALL_DESCRIPTORS` all five, and `BY_ENGINE_ID` maps every\n`EngineId`. The worker\nadds adapters for the local engines that are switched on through\n`local_engines.py::LocalEngineSettings` — the one resolver bootstrap, `worker`,\n`work` and `doctor` share.\n\nEach descriptor (`domain\u002Fengine.py::EngineDescriptor`) declares:\n- `engine_id`, `binary` — the executable name (e.g., `\"claudeloop\"`), `min_version`\n- `state_dir` — where runs are stored (e.g., `\".claudeloop\u002F\"`)\n- `done_marker` — the text signaling completion (e.g., `\"CLAUDELOOP_TASK_FULLY_COMPLETE\"`)\n- `capabilities` — which features it supports (`savepoints`, `unwind`, etc.). A\n  claim must agree with the facts below (`test_descriptors.py`): `mid_run_prompt`\n  exactly where `controls.prompt` is declared, `attachments` only where `images`\n  or `paste_images` is proven `True`, `web_search` only where the runner's `run`\n  takes `--web-search`\n- `effort_projection` — how vibey's 5-level ladder (`TRIVIAL, LOW, STANDARD, HIGH, MAX`)\n  maps to the engine's native flags\n- `auth_env` — environment variables that must be set (empty for gptossloop and qwenloop)\n- `env_passthrough` — the variables the engine's runner and vendor CLI read, passed\n  to its sessions (a trailing `*` names a prefix); nothing else reaches a session\n  unless the project declares it\n- `session_verb`, `isolation_flags` (per `IsolationLevel`)\n- `cost_per_mtok_in`\u002F`cost_per_mtok_out`, `context_window`, `base_weight` (rotation weight)\n- `tier` (`EngineTier.PAID` default, `LOCAL` for gptossloop, qwenloop and claudeloop-local) and\n  `doctor_args` (extra `doctor` arguments; claudeloop-local: `--profile NAME`)\n- `supports_cwd_flag` (default `True`; codexloop: `False`) and `plan_flag`\n  (default `None` = positional plan path; no current engine sets one)\n- `affordances` — `EngineAffordances`: `images`, `files`, `paste_text`,\n  `paste_images`, `plugins` (`PluginSystem`) and `mcp`, each `True`, `False` or\n  `None` (unknown, the default). `evidence` names, for every value that is set,\n  where the runner's own code shows it; a set value without evidence fails a\n  test. Never set one from memory or a vendor's marketing\n- `controls` — `EngineControls`: `stop`, `wind_down` and `prompt` as argv\n  templates after the binary (`{run_id}`, `{cwd}`, `{text}`), `None` where the\n  runner has no such verb or does not act on it. Tests read every template against\n  the runner's own Typer app the way click parses it\n- `events` — `EventLog`: the `path` template of its `events.jsonl` and its\n  `envelope` (`EventEnvelope`: `type`, `event_type+payload`, or `event_type`)\n\n**Effort projection example** (claudeloop, as in `descriptors.py`):\n\n```python\neffort_projection={\n    Effort.TRIVIAL: EngineInvocation((\"--preset\", \"low\", \"--effort\", \"low\"), achieved=Effort.TRIVIAL),\n    Effort.LOW: EngineInvocation((\"--preset\", \"low\", \"--effort\", \"medium\"), achieved=Effort.LOW),\n    Effort.STANDARD: EngineInvocation((\"--preset\", \"medium\", \"--effort\", \"high\"), achieved=Effort.STANDARD),\n    Effort.HIGH: EngineInvocation((\"--preset\", \"high\", \"--effort\", \"high\"), achieved=Effort.HIGH),\n    Effort.MAX: EngineInvocation((\"--preset\", \"high\", \"--effort\", \"max\"), achieved=Effort.MAX),\n}\n```\n\ngptossloop and qwenloop project effort onto `--max-turns` (8, 16, 40, 64, 96).\nclaudeloop-local passes `--profile NAME --preset low|low|medium|high|high` and\nnever `--effort`; HIGH and MAX report `achieved=STANDARD`, its honest ceiling.\n\nIf an engine **saturates**, the descriptor sets `achieved` to the tier it\nactually delivers. codexloop is the extreme case: its `run` has no effort flag,\nso every level projects to empty argv with `achieved=Effort.STANDARD`.\n`domain\u002Frotation.py::fidelity_factor(descriptor, requested)` computes the\n`Candidate.fidelity_factor` that scales the effective weight of engines that\nsaturate below the requested effort; `application\u002Fengine_selector.py` applies\nit.\n\nSee ADR-0006 (normalized effort ladder).\n\n## argv building\n\n`infrastructure\u002Fengines\u002Fargv.py::build_argv(descriptor, spec)` takes an\n`EngineDescriptor` and a `RunSpec` (fields: `run_id`, `worktree_path`,\n`prompt`, `effort`, `isolation`, optional `session_id` to resume) and\nproduces the command line — read the real function, it is short. As of\n2026-09-15 it emits, in order:\n\n1. `\u003Cbinary> run`, or `\u003Cbinary> resume \u003Csession_id>` when `spec.session_id` is set.\n2. For `run` only: the plan path `\u003Cworktree>\u002F.vibey\u002Fplans\u002F\u003Crun_id>.md`, prefixed\n   by `descriptor.plan_flag` when an engine sets one,\n   then `--run-id \u003Crun_id>` (so the adapter finds the run directory the process\n   writes to).\n3. `descriptor.invoke(effort).argv`.\n4. `descriptor.isolation_flags.get(isolation, ())`.\n5. `--cwd \u003Cworktree_path>`, only when `descriptor.supports_cwd_flag` (codexloop:\n   `False`).\n\n30 golden files under `tests\u002Finfrastructure\u002Fengines\u002Fgolden\u002F` (5 engines × 6\nefforts, ULTRA included; `test_argv.py` parametrizes over `ALL_DESCRIPTORS`) capture the\nexpected argv for each combination — the source of truth for the exact current\nshape.\n\n`argv.py::RUN_ARGV_TEMPLATE` (`RunArgvTemplate`) is `build_argv`'s `run` line with\nits per-run values as placeholders: `{binary}`, `run`, `{plan_flag?}` (only with a\n`plan_flag`), `{plan}`, `--run-id`, `{run_id}`, `{effort_argv...}`, and `--cwd\n{cwd}` when `supports_cwd_flag`. It is what `vibey loops` publishes for a caller\nthat starts a runner itself, such as the VS Code extension. Tests compare it with\n`build_argv` for every engine and effort, and read it, filled in at every effort\nand isolation level, against the runner's own `run` definition.\n\n## What `vibey loops` reports\n\n`vibey loops [--json]` (`application\u002Floops.py::LoopCatalog`, `cli\u002Floops.py`) lists\nthe two loops of sub-doctrine 8.c, each engine under the loop its tier puts it in,\nwith every effort's argv, achieved effort and model, and the descriptor's run\ntemplate, `affordances`, `controls`, `events` and env names (names only). It reads\nthe local switches (and whether each is `on_by_default`) and each local runner's\nmodel through `local_engines.py`, the resolvers\n`vibey doctor` reads. An engine canon 8.b repeals (`REPEALED_FROM_LOOPS`; empty\nsince OpenCode's engine was deleted) is listed with `repealed: true` and left out of\nevery by-effort view. The document for one\nfixed environment is committed as `tests\u002Fcli\u002Fgolden\u002Fvibey-loops.json`: after\nchanging a descriptor, regenerate it with\n`VIBEY_UPDATE_GOLDENS=1 uv run pytest tests\u002Fcli\u002Ftest_loops_cli.py -k golden` and\ncommit it with the change.\n\n## Capacity classification\n\n`infrastructure\u002Fengines\u002Fclassify.py::classify_capacity(engine_id, raw)` dispatches\nto one private classifier per engine (claudeloop-local shares claudeloop's) and\nmaps vendor-specific error shapes to vibey's `CapacityState`. claudeloop writes\nits capacity as the class *name* (`\"capacity\": \"CreditsExhausted\"`); both that and\nthe `{\"state\": ...}` mapping are read, and `BackendMisconfigured` maps to\n`AuthenticationFailed` (terminal, never credits). Exit 78 (EX_CONFIG,\n`EXIT_CODE_BACKEND_MISCONFIGURED`) is attributed to ENGINE, and an incomplete run\nthat exited 78 parks its BUILD job on an `engine_misconfigured` gate\n(`RunOutcome.misconfiguration_gate`) instead of retrying:\n\n```python\nAvailable | WindowExhausted | CreditsExhausted | AuthenticationFailed\n```\n\n**The critical distinction:** `WindowExhausted` has a `resets_at` deadline;\n`CreditsExhausted` does not. A window exhaustion is waitable; credits\nexhaustion requires a human top-up.\n\nEach engine's classifier pattern is versioned in `CREDITS_FIXTURES`,\n`WINDOW_FIXTURES`, `AUTH_FIXTURES`, and `AVAILABLE_FIXTURES` — shared between\nthe classifier's own tests and the conformance suite.\n\n**Note:** these are synthesized fixture payloads, not captured real vendor\nerrors. If you get access to real `*loop` binaries or real captured error\npayloads, this is the first thing to replace.\n\n## The conformance suite\n\n`application\u002Fconformance.py::run_conformance()` runs 9 named checks per\nengine (grep the file for the check-name strings if this list drifts):\n`binary` (installed + version), `flags` (`run --help` exposes what the\ndescriptor claims), `state_dir`, `run_dir_shape` (a real run produces\n`meta.json`\u002F`events.jsonl`\u002F`snapshots\u002Flatest.json` — this one races a real\nsubprocess's own startup time, not just an instant file check; read the\nfunction if you're touching it), `snapshot_schema`, `capacity_map`,\n`done_marker`, `control_plane`, `structured_verdict`.\n\nA failing conformance check marks that engine **ineligible** rather than\nletting it fail mid-cycle.\n\n```bash\nvibey doctor --conformance --record\n```\n\n`--record` persists the preflight and conformance result to `engine_health`.\nWithout a recorded pass the worker warns and never selects the engine for\nengine-driven jobs.\n\nLive runs of the suite are split in two modes (ADR-0030): `tests\u002Flive\u002F` with\n`@pytest.mark.live` runs conformance and rotation against `ScriptedEngine`\nand scripted stand-in binaries, with no model calls; `@pytest.mark.paid` spawns real binaries\nagainst real models and is excluded by default.\n\nSee ADR-0001 (orchestrate, do not reimplement).\n\n## When to read this skill\n\nBefore:\n- Adding a new engine.\n- Changing effort mappings.\n- Changing what an engine declares it can take, control or emit (`affordances`,\n  `controls`, `events`), or anything `vibey loops` reports.\n- Debugging why rotation is skipping an engine.\n- Updating capacity classification patterns after a vendor API change.\n",{"name":5,"description":7,"allowed-tools":24},"Read Grep","develop","ae32736a1aabddabca5d2c96d665aa0ebc7d8700",".claude\u002Fskills\u002Fvibey-engine-adapters",3,"https:\u002F\u002Fgithub.com\u002Fthe-vibey-project\u002Fvibey","https:\u002F\u002Fthe-vibey-project.github.io\u002Fvibey\u002F","https:\u002F\u002Fgithub.com\u002Fthe-vibey-project","https:\u002F\u002Fvibewithadam.matthewsteinberger.com","freedom for software engineers","2026-11-15 05:47:42",{"source":8,"skillName":5,"commands":36,"prompt":46,"zipAvailable":47},[37,40,43],{"tool":38,"command":39},"npx","npx skills add the-vibey-project\u002Fvibey --skill vibey-engine-adapters",{"tool":41,"command":42},"bunx","bunx skills add the-vibey-project\u002Fvibey --skill vibey-engine-adapters",{"tool":44,"command":45},"pnpm","pnpm dlx skills add the-vibey-project\u002Fvibey --skill vibey-engine-adapters","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fthe-vibey-project\u002Fvibey\u002Fblob\u002Fdevelop\u002F.claude\u002Fskills\u002Fvibey-engine-adapters\u002FSKILL.md",true,[],[50,57,64,71,78,85],{"skillNo":51,"name":52,"nameZh":6,"description":53,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":54,"categories":55,"keywords":56,"publishedAt":19},"01M7AT1FQJAE1FQYAMDTF490Y4","white-paper-writing","Use when writing white papers, technical reports, policy documents, thought leadership pieces, or any long-form authoritative document. Triggers on requests to write, structure, outline, or review white papers, technical reports, position papers, policy briefs, or evidence-driven arguments. Also use for B2B content marketing strategy, technical documentation requiring authority, academic-style reports, or any document that must educate while persuading. Use when someone asks \"how should I structure this\" for a long-form document.","https:\u002F\u002Fgithub.com\u002Fthe-vibey-project\u002Fvibey\u002Fblob\u002Fdevelop\u002Fsrc\u002Fvibey_tools\u002Fskills\u002Fplugins\u002Fwriting-craft\u002Fskills\u002Fwhite-paper-writing\u002FSKILL.md",[],[],{"skillNo":58,"name":59,"nameZh":6,"description":60,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":61,"categories":62,"keywords":63,"publishedAt":19},"01M7AT16BJRJJKK2MASXRZS76G","prose-technical-mechanics","Use when editing or writing prose at a technical\u002Fmechanical level: choosing between Anglo-Saxon and Latinate diction, placing information in topic vs stress positions, writing periodic vs cumulative sentences, handling sentence rhythm, punctuation as logic, transitions, paragraph structure, or phonesthetics. Use when someone wants to understand WHY prose works or doesn't, not just surface-level style advice. Triggers on word choice, sentence structure, emphasis, rhythm, diction, or any deep writing mechanics question.","https:\u002F\u002Fgithub.com\u002Fthe-vibey-project\u002Fvibey\u002Fblob\u002Fdevelop\u002Fsrc\u002Fvibey_tools\u002Fskills\u002Fplugins\u002Fwriting-craft\u002Fskills\u002Fprose-technical-mechanics\u002FSKILL.md",[],[],{"skillNo":65,"name":66,"nameZh":6,"description":67,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":68,"categories":69,"keywords":70,"publishedAt":19},"01M7AT0W9HT0ZZ9Y287NW99MR3","prose-mechanics","Use when writing, editing, or analyzing prose style; when trying to avoid generic AI-sounding writing; when applying specific prose styles such as journalistic, academic, narrative, KJV biblical, Hemingway plain, Latinate\u002FJamesian, Orwellian, Augustan, Victorian, Early Modern (Bacon, Browne, Milton), or free indirect discourse; or when coaching someone on writing voice and mechanics. Triggers on any request to improve, analyze, or write in a specific prose style, to fix \"AI-sounding\" writing, to make prose more vivid or concrete, to vary sentence rhythm, or to understand how a particular writer achieves their effects.","https:\u002F\u002Fgithub.com\u002Fthe-vibey-project\u002Fvibey\u002Fblob\u002Fdevelop\u002Fsrc\u002Fvibey_tools\u002Fskills\u002Fplugins\u002Fwriting-craft\u002Fskills\u002Fprose-mechanics\u002FSKILL.md",[],[],{"skillNo":72,"name":73,"nameZh":6,"description":74,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":75,"categories":76,"keywords":77,"publishedAt":19},"01M7AT0KR635JX66X2X6F3E2CP","narrative-structure","Use when structuring stories, pitches, presentations, white papers, or any persuasive narrative; analyzing the hero's journey in fiction or non-fiction; applying StoryBrand for business communication; designing narrative arcs for thought leadership; or understanding Vogler, Snyder, Propp, or Campbell frameworks. Triggers on any narrative structure, storytelling, pitch structure, StoryBrand, hero's journey, three-act structure, Freytag, Save the Cat, narrative arc, or \"how should I structure this story\u002Fpitch\u002Fpresentation\" request.","https:\u002F\u002Fgithub.com\u002Fthe-vibey-project\u002Fvibey\u002Fblob\u002Fdevelop\u002Fsrc\u002Fvibey_tools\u002Fskills\u002Fplugins\u002Fwriting-craft\u002Fskills\u002Fnarrative-structure\u002FSKILL.md",[],[],{"skillNo":79,"name":80,"nameZh":6,"description":81,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":82,"categories":83,"keywords":84,"publishedAt":19},"01M7AT0AKGW09NKKZDYBT8VRDE","legal-brief-writing","Use when writing legal briefs, motions, or any court filing; when analyzing judicial cognition and persuasion; when applying elite brief-writing techniques from Roberts, Clement, Kagan, Garner; or when structuring legal arguments for maximum persuasion. Also use for autistic\u002Fneurodivergent advocates who need to understand how their natural communication style maps to elite legal advocacy. Triggers on any legal writing, brief drafting, motion preparation, or legal argument structuring request.","https:\u002F\u002Fgithub.com\u002Fthe-vibey-project\u002Fvibey\u002Fblob\u002Fdevelop\u002Fsrc\u002Fvibey_tools\u002Fskills\u002Fplugins\u002Fwriting-craft\u002Fskills\u002Flegal-brief-writing\u002FSKILL.md",[],[],{"skillNo":86,"name":87,"nameZh":6,"description":88,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":89,"categories":90,"keywords":91,"publishedAt":19},"01M7AT00VWPS4Q8B5VEMXX9NQT","journal-publishability-criteria","Use whenever a research paper, article or preprint is being written, revised, reviewed or published, and specifically before every publication of docs\u002Fpaper.md. Covers what legitimate journals actually gate on, in order of gating — the editor's desk screen (scope, novelty, package problems), what reviewers judge (methodological soundness, claims the evidence can carry, statistical and qualitative reporting), EQUATOR reporting guidelines, the ICMJE authorship criteria, COPE's view of text recycling, the near-universal generative-AI policy (no AI author, disclosure, author responsibility), TOP 2025 transparency standards, how to verify a journal is legitimate, submitting without an institution, and a pre-submission checklist. Triggers on requests to evaluate, review, prepare or submit a paper, to judge publishability, to write a declarations or data-availability section, to disclose AI use, or to check a journal.","https:\u002F\u002Fgithub.com\u002Fthe-vibey-project\u002Fvibey\u002Fblob\u002Fdevelop\u002Fsrc\u002Fvibey_tools\u002Fskills\u002Fplugins\u002Fwriting-craft\u002Fskills\u002Fjournal-publishability-criteria\u002FSKILL.md",[],[]]