[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M732AE8YGDZJJS29K8SJDC38":3,"skill-same:01M732AE8YGDZJJS29K8SJDC38":47},{"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":24,"commitSha":25,"skillDirectory":26,"forksCount":27,"repositoryHtmlUrl":28,"repositoryHomepageUrl":6,"ownerHtmlUrl":29,"ownerBlogUrl":30,"ownerDescription":31,"updatedAt":32,"install":33,"resources":46},"01M732AE8YGDZJJS29K8SJDC38","engineering-conventions",null,"Guidelines and non-negotiable engineering invariants for modifying opencode-swarm. Load before architecture, plugin initialization, subprocess, tool registration, plan durability, .swarm storage, runtime portability, session\u002Fglobal state, guardrails\u002Fretry, chat\u002Fsystem message hooks, or release\u002Fcache changes. Authoritative source: AGENTS.md at the repo root and docs\u002Fengineering-invariants.md.","djimit\u002Fdjimitflo","djimit","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F19958832?v=4","01M7327CH792DZPFZPYAEFPRXT","Dutch Dim","01M7327CHWPSXT9AWE4MPWCX9Q",2,"MIT","https:\u002F\u002Fgithub.com\u002Fdjimit\u002Fdjimitflo\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Fengineering-conventions\u002FSKILL.md",[],[],"2026-11-11 15:11:14",false,"---\nname: engineering-conventions\ndescription: >\n  Guidelines and non-negotiable engineering invariants for modifying opencode-swarm.\n  Load before architecture, plugin initialization, subprocess, tool registration, plan\n  durability, .swarm storage, runtime portability, session\u002Fglobal state, guardrails\u002Fretry,\n  chat\u002Fsystem message hooks, or release\u002Fcache changes. Authoritative source: AGENTS.md\n  at the repo root and docs\u002Fengineering-invariants.md.\n---\n\n# Engineering Conventions for opencode-swarm\n\n**Authoritative source:** [`AGENTS.md`](..\u002F..\u002F..\u002FAGENTS.md) at the repo root and [`docs\u002Fengineering-invariants.md`](..\u002F..\u002F..\u002Fdocs\u002Fengineering-invariants.md). This skill is a pointer + summary so the OpenCode agent loads the right invariants before touching dangerous areas. **Read `AGENTS.md` first.** When this skill conflicts with `AGENTS.md`, `AGENTS.md` wins.\n\n## When to load this skill\n\nLoad this skill **before** beginning implementation work that touches any of:\n\n- `src\u002Findex.ts` (plugin entry \u002F `initializeOpenCodeSwarm`)\n- `src\u002Fhooks\u002F*` (any hook that may run during init or QA review)\n- `src\u002Ftools\u002F*` (tool registration, working-directory anchoring, test_runner)\n- `src\u002Futils\u002Fbun-compat.ts` (subprocess shim — every spawn in the repo eventually flows through here)\n- `src\u002Futils\u002Ftimeout.ts` (the `withTimeout` primitive used by every bounded init step)\n- `src\u002Futils\u002Fgitignore-warning.ts` (Git hygiene; runs on plugin init path)\n- `package.json`, build configuration, `dist\u002F`, plugin export shape\n- Plan ledger \u002F projection \u002F checkpoint code (`src\u002Fplan\u002F*`, `.swarm\u002Fplan-*`)\n- Session \u002F guardrails \u002F runtime state (`src\u002Fstate.ts`, `src\u002Fhooks\u002Fguardrails.ts`)\n- Tests involving subprocesses, plugin startup, `mock.module`, or temp directories\n\nIf you are not sure whether you are touching one of these, you are touching one of these.\n\n## Highest-risk invariants (the ones that have already shipped regressions)\n\nThe full list of 12 invariants is in `AGENTS.md`. The four that have caused the most recent production regressions:\n\n1. **Plugin initialization is bounded and fail-open.** Every awaited operation on the plugin-init path must be wrapped in `withTimeout(...)` and degrade non-fatally on timeout. Issue #704 (v7.0.3) and the v7.3.3 git-hygiene regression both stem from violating this. The OpenCode plugin host silently drops a plugin whose entry never resolves; users see \"no agents in TUI \u002F GUI\" with no error.\n2. **Subprocesses are bounded, non-interactive, and killable.** Every `bunSpawn(['\u003Cbin>', ...])` call must pass `cwd`, `stdin: 'ignore'` (unless intentionally interactive), `timeout: \u003Cms>`, bounded stdio, and call `proc.kill()` in a `finally`. An outer `withTimeout` is not enough — it lets the awaiter proceed but does not abort the child.\n3. **Runtime portability — Node-ESM-loadable + v1 plugin shape.** No top-level `bun:` imports in `dist\u002Findex.js`. Default export is `{ id, server }`. All `Bun.*` calls go through `src\u002Futils\u002Fbun-compat.ts`. v6.86.8 \u002F v6.86.9 are the cautionary tales.\n4. **Test mock isolation.** `mock.module(...)` leaks across files in Bun's shared test-runner process. Prefer, in order: (a) `_test_exports` for pure function testing with zero mocks, (b) `_internals` dependency-injection seam for within-module mocking (see `src\u002Futils\u002Fgitignore-warning.ts:_internals` and `src\u002Fhooks\u002Fdiff-scope.ts:_internals`), (c) `mock.module` only when unavoidable. Restore in `afterEach`. The writing-tests skill covers all three tiers in detail; load it before modifying tests.\n\n## Cross-link: writing tests\n\nFor test changes, also load [`.opencode\u002Fskills\u002Fwriting-tests\u002FSKILL.md`](..\u002Fwriting-tests\u002FSKILL.md). It covers `bun:test` API, mock isolation rules, CI per-file isolation, and cross-platform anti-patterns.\n\n## Hard warning: do NOT use broad `test_runner` for repo validation\n\nThe OpenCode `test_runner` tool is for **targeted agent validation** with explicit `files: [...]` or small targeted scopes. It is not the way to validate the full repo from inside an OpenCode session. In this repo:\n\n- `MAX_SAFE_TEST_FILES = 50` (`src\u002Ftools\u002Ftest-runner.ts`). Resolutions exceeding this return `outcome: 'scope_exceeded'` with a SKIP. Do not lean on this — broad scopes can stall or kill OpenCode before that guard fires.\n- For repo validation, run the shell commands in `contributing.md` \u002F `TESTING.md` directly (per-file isolation loops + tier orchestration).\n- `scope: 'all'` requires `allow_full_suite: true` and is intended for opt-in CI mirrors only. Default to `files: [...]` instead.\n\n## The invariant-audit gate (PR-time)\n\nEvery PR that touches a relevant area must include an `## Invariant audit` section in its description. The format is in `AGENTS.md` (\"Invariant audit required in PRs\"). The `commit-pr` skill enforces this gate before push\u002FPR — load it before committing.\n\nIf you cannot prove a touched invariant from source and test output, **do not push**.\n\n## Init-path-safe imports (invariant 1 deep-dive)\n\nThe most expensive invariant-1 violations come from **transitive import chains** that silently load heavy modules (WASM, tree-sitter) at plugin init time. A single `import { X } from '..\u002F..\u002Flang'` in a tool-time module can transitively load `runtime.ts` → `web-tree-sitter` (heavy WASM), spiking init latency well past the repro-704 T1 deadline (observed during issue #1471 development).\n\n### The lang barrel trap\n\n`src\u002Flang\u002Findex.ts` re-exports from `.\u002Fruntime`, which statically imports `web-tree-sitter`. Importing **anything** from the barrel (`from '..\u002F..\u002Flang'`) transitively loads WASM at module-eval time.\n\n**Wrong:** `import { LANGUAGE_REGISTRY } from '..\u002F..\u002Flang'` — loads runtime → web-tree-sitter.\n**Right:** `import { LANGUAGE_REGISTRY } from '..\u002F..\u002Flang\u002Fprofiles'` — loads only profiles (string data, no WASM).\n\n### Type-only vs value imports\n\n- `import type { Query } from 'web-tree-sitter'` — **safe** (erased at compile time, no module load).\n- `import { Query } from 'web-tree-sitter'` — **unsafe** on the init path (loads the WASM module).\n- For value dependencies on heavy modules in init-reachable code, use dynamic `import()` inside an async function (deferred to first call, not module load).\n\n### The `--external` build flag\n\nDynamic `import('web-tree-sitter')` only defers loading at runtime if `--external web-tree-sitter` is set in the bun build config. Without it, bun bundles web-tree-sitter inline and the dynamic import resolves from the bundle (no deferral). Check `package.json` build scripts for the flag.\n\n### Verification checklist\n\nFor any import-chain change touching `src\u002Flang\u002F`, `runtime`, or `web-tree-sitter`:\n1. Trace the transitive chain from `src\u002Findex.ts` to verify no heavy module loads at init.\n2. Rebuild dist: `bun run build` (stale dist gives false regressions).\n3. Run `node scripts\u002Frepro-704.mjs` — T1 must be under 400ms.\n4. Run `bun --smol test tests\u002Funit\u002Flang\u002Fsymbol-graph-init-purity.test.ts` — init-path purity tests must pass.\n\n## Tool version parity (local vs CI)\n\n**Tool versions must match CI.** When `package.json` pins a tool version (e.g., `@biomejs\u002Fbiome@2.3.14`, `@biomejs\u002Fbiome@^2`, or any other versioned dev dependency), invoke it **with the pinned version** during local validation. Unversioned `bunx biome` resolves to a different version than the CI gate uses, and a CI-blocking failure can be invisible to local pre-commit validation.\n\nExamples:\n- Pinned biome: `bunx @biomejs\u002Fbiome@\u003Cversion> ci .` (substitute `\u003Cversion>` from `package.json`).\n- Unversioned `bunx biome ci .` resolves to whatever Bun's `bunx` registry returns at run time — historically 0.3.x vs the pinned 2.x.\n\nThe `commit-pr` skill Tier 1 - quality section pins the biome command to the package.json version; this is the canonical pattern for any tool where local and CI versions could diverge. Apply the same discipline to ESLint, Prettier, TypeScript, and any other versioned dev dependency.\n\n**Why this matters:** PR #1503 (telemetry rotation fix) had a biome 2.3.14 `organizeImports` failure on the `.\u002Ftelemetry` import block that was invisible to local `bunx biome` (which resolved to 0.3.3 with no equivalent rule). The reviewer caught it from CI logs, not local validation. Pin tool versions to close the local\u002FCI parity gap.\n\n## Skill mirror contract\n\nThe cross-tree skill mirror contract is the authoritative registry at `src\u002Fconfig\u002Fskill-mirrors.ts`. If your PR modifies `.opencode\u002Fskills\u002F\u003CX>\u002FSKILL.md` or `.claude\u002Fskills\u002F\u003CX>\u002FSKILL.md`, consult that file to determine the contract kind for skill `\u003CX>`:\n\n- **`identical`:** `.opencode` and `.claude` SKILL.md must be byte-identical (the `canonical` field records which side wins when they drift). Update both trees byte-for-byte in the same commit. Verify with `bun run drift:check`. PR #1512 (lane-dispatch) introduced drift in council\u002Fdeep-dive by only updating `.opencode` — a contract violation.\n- **`divergent`:** both must exist but content intentionally differs per runtime. Examples: `engineering-conventions` is divergent (different frontmatter, different conventions per Claude Code vs OpenCode). `writing-tests` is classified divergent because the additional-contract model does not yet have an adapter kind, but operationally `.opencode\u002Fskills\u002Fwriting-tests\u002FSKILL.md` is canonical and `.claude\u002Fskills\u002Fwriting-tests\u002FSKILL.md` delegates to it.\n- **`opencode-only`:** `.opencode` exists; no `.claude` mirror expected. Examples: `loop` (would shadow Claude Code's built-in `\u002Floop`), `running-tests` (OpenCode-runtime guidance).\n- **Adapter shim pattern:** for architect MODE skills like `swarm-pr-review` and `swarm-pr-feedback`, the `.claude` and `.agents` files are thin adapter shims that delegate to the canonical `.opencode` file via `expectedCanonicalRef`. When updating these, the canonical content goes in `.opencode`; the adapter shim typically needs no change unless the cross-tree delegation interface changes.\n\n**If your PR modifies a `.opencode\u002Fskills\u002F\u003CX>\u002FSKILL.md` file:** check `src\u002Fconfig\u002Fskill-mirrors.ts` for the contract, then run `bun run drift:check` locally before pushing. Mirror drift is currently a soft-warn (`DRIFT_CHECK_ENFORCE=1` would make it hard-fail). The drift-check CI job surfaces drift as an issue comment, not a blocking check — but a drift between canonical and mirror means Claude Code agents reading the mirror get stale instructions.\n\n## Sandbox env overrides (subprocess-safety deep-dive)\n\nWhen a sandbox executor (`src\u002Fsandbox\u002F{linux,macos,win32}\u002F*.ts`) interpolates environment variables into a sandbox profile, a bwrap rule, or a PowerShell `-EnvironmentVariables` block, the following rules apply — they exist because a future shell-injection regression in any new sandbox path would be a security vulnerability, not just a bug:\n\n- **Keys must match POSIX env-var name syntax.** Every env key must be validated against the regex `\u002F^[A-Za-z_][A-Za-z0-9_]*$\u002F` (a leading letter or underscore, then letters\u002Fdigits\u002Funderscores) before being interpolated. Define or reuse a single `isValidEnvKey(key: string): boolean` helper colocated with the `SandboxExecutor` interface in `src\u002Fsandbox\u002Fexecutor.ts` (around line 24+); do not duplicate the regex inline at every call site. Keys that fail validation must be silently dropped (not raised) so that one bad caller cannot wedge the sandbox path — but the drop must be observable in the advisory\u002Fobservability layer (`pendingAdvisoryMessages` or structured log), never silent.\n- **Values must be shell-quoted or treated as opaque single tokens.** On POSIX, prepend a leading single quote, escape any embedded single quotes by replacing `'` with `'\\''`, and append a trailing single quote. On Windows PowerShell, **prefer single-quoted literal contexts (e.g. `'$env:NAME'`) and run values through a `psStringEscape`-style helper that escapes backtick, `$`, `\"`, and `` ` ``** (the special characters in double-quoted PowerShell strings). Single-quoted PowerShell strings are literal — only `'` needs escaping, doubling it to `''`. If a context requires double-quoted PS values, escape embedded `\"` as `` ` ``, backtick as `` `` ``, and `$` as `` ` `` (backtick is the PS escape character in double-quoted strings; `$` must be escaped to prevent variable expansion). On bwrap, always pass values as separate argv tokens after the `--setenv` flag (`--setenv KEY VALUE`, two tokens), never as a single concatenated `KEY=VALUE` token that an intermediate shell would interpret.\n- **Use the array-form argv for every sandbox subprocess.** Never `shell:`-interpolate. The same invariant-3 rules (`array-form spawn`, `stdin: 'ignore'`, `cwd`, `timeout`, `proc.kill()` in `finally`) apply to sandbox spawns as to any other subprocess — see the `subprocess-safety` cross-link.\n\n## Sandbox fallback parity (Windows and Linux)\n\n`sandbox\u002F{linux,macos,win32}\u002F*.ts` has primary executors plus legacy fallbacks (Windows `NativeWindowsSandboxExecutor` + `RestrictedEnvironmentExecutor` \u002F PowerShell wrapper, Linux `BubblewrapSandboxExecutor` + no-sandbox fallback). When you modify any of the following on the primary executor, you MUST update the fallback path in the same change to keep behavior parity and add a parity test:\n\n- `getEnvOverrides` signature or merge semantics.\n- `wrapCommand` scoping rules (allowed roots, read-only mounts, temp-dir allocation).\n- `isAvailable()` \u002F capability probe logic.\n- Failure-mode handling (does a missing sandbox envelope hard-fail or soft-fail to env-only isolation?).\n- Scope-materialization for lane-scoped resources.\n\nA divergence between primary and fallback that is not exercised by a parity test is a regression. The existing per-OS test files `tests\u002Funit\u002Fsandbox\u002F{linux,macos,win32}.test.ts` must continue to cover both the primary and fallback paths after every env-affecting change — extend these tests rather than relying on dedicated sandbox-envoverride test files that may or may not exist in your branch.\n\n## SAST baseline capturing (differential scanning)\n\nThe `sast_scan` tool supports `capture_baseline: true` with a `phase` parameter\nto snapshot pre-existing findings. Subsequent scans with the same `phase` value\nperform differential checking — they only fail on **new** findings, not\npre-existing ones.\n\n### When to capture a baseline\n\n- **Before Phase 1 code changes.** The baseline must reflect the state of the\n  codebase *before* any new work is done. This ensures the differential scan\n  catches findings introduced by the current session's changes.\n\n### Critical safety guard\n\n**NEVER capture a baseline after code changes have been made in a phase.**\nA baseline captured post-edit silently encodes the very bugs the scan is meant\nto catch as \"pre-existing,\" suppressing them indefinitely. This turns the SAST\ngate into theater.\n\n### How to use it\n\n1. Identify the files to scan. In a phase, use the union of declared task-scope\n   files plus files the coder is expected to touch. Derive the list from\n   `declare_scope` outputs, `git diff --name-only`, or the phase's task specs.\n2. Before any coder delegation in Phase 1, capture the baseline:\n   ```\n   sast_scan(directory, changed_files=[...], capture_baseline=true, phase=1)\n   ```\n3. After coder work, scan the same file set:\n   ```\n   sast_scan(directory, changed_files=[...], phase=1)\n   ```\n   This returns only NEW findings (absent from the baseline).\n4. If a pre-existing finding is legitimately fixed, the baseline can be\n   re-captured at the start of the next phase with the updated file list.\n\n### Why this matters\n\nDuring PR #1704 review, SAST flagged `RegExp.prototype.exec()` as\n\"command injection via child_process.exec()\" — a false positive that blocked\nthe gate. With a baseline captured before the phase, this pre-existing false\npositive would have been suppressed, and only genuinely new findings would\nsurface.\n","# Engineering Conventions for opencode-swarm\n\n**Authoritative source:** [`AGENTS.md`](..\u002F..\u002F..\u002FAGENTS.md) at the repo root and [`docs\u002Fengineering-invariants.md`](..\u002F..\u002F..\u002Fdocs\u002Fengineering-invariants.md). This skill is a pointer + summary so the OpenCode agent loads the right invariants before touching dangerous areas. **Read `AGENTS.md` first.** When this skill conflicts with `AGENTS.md`, `AGENTS.md` wins.\n\n## When to load this skill\n\nLoad this skill **before** beginning implementation work that touches any of:\n\n- `src\u002Findex.ts` (plugin entry \u002F `initializeOpenCodeSwarm`)\n- `src\u002Fhooks\u002F*` (any hook that may run during init or QA review)\n- `src\u002Ftools\u002F*` (tool registration, working-directory anchoring, test_runner)\n- `src\u002Futils\u002Fbun-compat.ts` (subprocess shim — every spawn in the repo eventually flows through here)\n- `src\u002Futils\u002Ftimeout.ts` (the `withTimeout` primitive used by every bounded init step)\n- `src\u002Futils\u002Fgitignore-warning.ts` (Git hygiene; runs on plugin init path)\n- `package.json`, build configuration, `dist\u002F`, plugin export shape\n- Plan ledger \u002F projection \u002F checkpoint code (`src\u002Fplan\u002F*`, `.swarm\u002Fplan-*`)\n- Session \u002F guardrails \u002F runtime state (`src\u002Fstate.ts`, `src\u002Fhooks\u002Fguardrails.ts`)\n- Tests involving subprocesses, plugin startup, `mock.module`, or temp directories\n\nIf you are not sure whether you are touching one of these, you are touching one of these.\n\n## Highest-risk invariants (the ones that have already shipped regressions)\n\nThe full list of 12 invariants is in `AGENTS.md`. The four that have caused the most recent production regressions:\n\n1. **Plugin initialization is bounded and fail-open.** Every awaited operation on the plugin-init path must be wrapped in `withTimeout(...)` and degrade non-fatally on timeout. Issue #704 (v7.0.3) and the v7.3.3 git-hygiene regression both stem from violating this. The OpenCode plugin host silently drops a plugin whose entry never resolves; users see \"no agents in TUI \u002F GUI\" with no error.\n2. **Subprocesses are bounded, non-interactive, and killable.** Every `bunSpawn(['\u003Cbin>', ...])` call must pass `cwd`, `stdin: 'ignore'` (unless intentionally interactive), `timeout: \u003Cms>`, bounded stdio, and call `proc.kill()` in a `finally`. An outer `withTimeout` is not enough — it lets the awaiter proceed but does not abort the child.\n3. **Runtime portability — Node-ESM-loadable + v1 plugin shape.** No top-level `bun:` imports in `dist\u002Findex.js`. Default export is `{ id, server }`. All `Bun.*` calls go through `src\u002Futils\u002Fbun-compat.ts`. v6.86.8 \u002F v6.86.9 are the cautionary tales.\n4. **Test mock isolation.** `mock.module(...)` leaks across files in Bun's shared test-runner process. Prefer, in order: (a) `_test_exports` for pure function testing with zero mocks, (b) `_internals` dependency-injection seam for within-module mocking (see `src\u002Futils\u002Fgitignore-warning.ts:_internals` and `src\u002Fhooks\u002Fdiff-scope.ts:_internals`), (c) `mock.module` only when unavoidable. Restore in `afterEach`. The writing-tests skill covers all three tiers in detail; load it before modifying tests.\n\n## Cross-link: writing tests\n\nFor test changes, also load [`.opencode\u002Fskills\u002Fwriting-tests\u002FSKILL.md`](..\u002Fwriting-tests\u002FSKILL.md). It covers `bun:test` API, mock isolation rules, CI per-file isolation, and cross-platform anti-patterns.\n\n## Hard warning: do NOT use broad `test_runner` for repo validation\n\nThe OpenCode `test_runner` tool is for **targeted agent validation** with explicit `files: [...]` or small targeted scopes. It is not the way to validate the full repo from inside an OpenCode session. In this repo:\n\n- `MAX_SAFE_TEST_FILES = 50` (`src\u002Ftools\u002Ftest-runner.ts`). Resolutions exceeding this return `outcome: 'scope_exceeded'` with a SKIP. Do not lean on this — broad scopes can stall or kill OpenCode before that guard fires.\n- For repo validation, run the shell commands in `contributing.md` \u002F `TESTING.md` directly (per-file isolation loops + tier orchestration).\n- `scope: 'all'` requires `allow_full_suite: true` and is intended for opt-in CI mirrors only. Default to `files: [...]` instead.\n\n## The invariant-audit gate (PR-time)\n\nEvery PR that touches a relevant area must include an `## Invariant audit` section in its description. The format is in `AGENTS.md` (\"Invariant audit required in PRs\"). The `commit-pr` skill enforces this gate before push\u002FPR — load it before committing.\n\nIf you cannot prove a touched invariant from source and test output, **do not push**.\n\n## Init-path-safe imports (invariant 1 deep-dive)\n\nThe most expensive invariant-1 violations come from **transitive import chains** that silently load heavy modules (WASM, tree-sitter) at plugin init time. A single `import { X } from '..\u002F..\u002Flang'` in a tool-time module can transitively load `runtime.ts` → `web-tree-sitter` (heavy WASM), spiking init latency well past the repro-704 T1 deadline (observed during issue #1471 development).\n\n### The lang barrel trap\n\n`src\u002Flang\u002Findex.ts` re-exports from `.\u002Fruntime`, which statically imports `web-tree-sitter`. Importing **anything** from the barrel (`from '..\u002F..\u002Flang'`) transitively loads WASM at module-eval time.\n\n**Wrong:** `import { LANGUAGE_REGISTRY } from '..\u002F..\u002Flang'` — loads runtime → web-tree-sitter.\n**Right:** `import { LANGUAGE_REGISTRY } from '..\u002F..\u002Flang\u002Fprofiles'` — loads only profiles (string data, no WASM).\n\n### Type-only vs value imports\n\n- `import type { Query } from 'web-tree-sitter'` — **safe** (erased at compile time, no module load).\n- `import { Query } from 'web-tree-sitter'` — **unsafe** on the init path (loads the WASM module).\n- For value dependencies on heavy modules in init-reachable code, use dynamic `import()` inside an async function (deferred to first call, not module load).\n\n### The `--external` build flag\n\nDynamic `import('web-tree-sitter')` only defers loading at runtime if `--external web-tree-sitter` is set in the bun build config. Without it, bun bundles web-tree-sitter inline and the dynamic import resolves from the bundle (no deferral). Check `package.json` build scripts for the flag.\n\n### Verification checklist\n\nFor any import-chain change touching `src\u002Flang\u002F`, `runtime`, or `web-tree-sitter`:\n1. Trace the transitive chain from `src\u002Findex.ts` to verify no heavy module loads at init.\n2. Rebuild dist: `bun run build` (stale dist gives false regressions).\n3. Run `node scripts\u002Frepro-704.mjs` — T1 must be under 400ms.\n4. Run `bun --smol test tests\u002Funit\u002Flang\u002Fsymbol-graph-init-purity.test.ts` — init-path purity tests must pass.\n\n## Tool version parity (local vs CI)\n\n**Tool versions must match CI.** When `package.json` pins a tool version (e.g., `@biomejs\u002Fbiome@2.3.14`, `@biomejs\u002Fbiome@^2`, or any other versioned dev dependency), invoke it **with the pinned version** during local validation. Unversioned `bunx biome` resolves to a different version than the CI gate uses, and a CI-blocking failure can be invisible to local pre-commit validation.\n\nExamples:\n- Pinned biome: `bunx @biomejs\u002Fbiome@\u003Cversion> ci .` (substitute `\u003Cversion>` from `package.json`).\n- Unversioned `bunx biome ci .` resolves to whatever Bun's `bunx` registry returns at run time — historically 0.3.x vs the pinned 2.x.\n\nThe `commit-pr` skill Tier 1 - quality section pins the biome command to the package.json version; this is the canonical pattern for any tool where local and CI versions could diverge. Apply the same discipline to ESLint, Prettier, TypeScript, and any other versioned dev dependency.\n\n**Why this matters:** PR #1503 (telemetry rotation fix) had a biome 2.3.14 `organizeImports` failure on the `.\u002Ftelemetry` import block that was invisible to local `bunx biome` (which resolved to 0.3.3 with no equivalent rule). The reviewer caught it from CI logs, not local validation. Pin tool versions to close the local\u002FCI parity gap.\n\n## Skill mirror contract\n\nThe cross-tree skill mirror contract is the authoritative registry at `src\u002Fconfig\u002Fskill-mirrors.ts`. If your PR modifies `.opencode\u002Fskills\u002F\u003CX>\u002FSKILL.md` or `.claude\u002Fskills\u002F\u003CX>\u002FSKILL.md`, consult that file to determine the contract kind for skill `\u003CX>`:\n\n- **`identical`:** `.opencode` and `.claude` SKILL.md must be byte-identical (the `canonical` field records which side wins when they drift). Update both trees byte-for-byte in the same commit. Verify with `bun run drift:check`. PR #1512 (lane-dispatch) introduced drift in council\u002Fdeep-dive by only updating `.opencode` — a contract violation.\n- **`divergent`:** both must exist but content intentionally differs per runtime. Examples: `engineering-conventions` is divergent (different frontmatter, different conventions per Claude Code vs OpenCode). `writing-tests` is classified divergent because the additional-contract model does not yet have an adapter kind, but operationally `.opencode\u002Fskills\u002Fwriting-tests\u002FSKILL.md` is canonical and `.claude\u002Fskills\u002Fwriting-tests\u002FSKILL.md` delegates to it.\n- **`opencode-only`:** `.opencode` exists; no `.claude` mirror expected. Examples: `loop` (would shadow Claude Code's built-in `\u002Floop`), `running-tests` (OpenCode-runtime guidance).\n- **Adapter shim pattern:** for architect MODE skills like `swarm-pr-review` and `swarm-pr-feedback`, the `.claude` and `.agents` files are thin adapter shims that delegate to the canonical `.opencode` file via `expectedCanonicalRef`. When updating these, the canonical content goes in `.opencode`; the adapter shim typically needs no change unless the cross-tree delegation interface changes.\n\n**If your PR modifies a `.opencode\u002Fskills\u002F\u003CX>\u002FSKILL.md` file:** check `src\u002Fconfig\u002Fskill-mirrors.ts` for the contract, then run `bun run drift:check` locally before pushing. Mirror drift is currently a soft-warn (`DRIFT_CHECK_ENFORCE=1` would make it hard-fail). The drift-check CI job surfaces drift as an issue comment, not a blocking check — but a drift between canonical and mirror means Claude Code agents reading the mirror get stale instructions.\n\n## Sandbox env overrides (subprocess-safety deep-dive)\n\nWhen a sandbox executor (`src\u002Fsandbox\u002F{linux,macos,win32}\u002F*.ts`) interpolates environment variables into a sandbox profile, a bwrap rule, or a PowerShell `-EnvironmentVariables` block, the following rules apply — they exist because a future shell-injection regression in any new sandbox path would be a security vulnerability, not just a bug:\n\n- **Keys must match POSIX env-var name syntax.** Every env key must be validated against the regex `\u002F^[A-Za-z_][A-Za-z0-9_]*$\u002F` (a leading letter or underscore, then letters\u002Fdigits\u002Funderscores) before being interpolated. Define or reuse a single `isValidEnvKey(key: string): boolean` helper colocated with the `SandboxExecutor` interface in `src\u002Fsandbox\u002Fexecutor.ts` (around line 24+); do not duplicate the regex inline at every call site. Keys that fail validation must be silently dropped (not raised) so that one bad caller cannot wedge the sandbox path — but the drop must be observable in the advisory\u002Fobservability layer (`pendingAdvisoryMessages` or structured log), never silent.\n- **Values must be shell-quoted or treated as opaque single tokens.** On POSIX, prepend a leading single quote, escape any embedded single quotes by replacing `'` with `'\\''`, and append a trailing single quote. On Windows PowerShell, **prefer single-quoted literal contexts (e.g. `'$env:NAME'`) and run values through a `psStringEscape`-style helper that escapes backtick, `$`, `\"`, and `` ` ``** (the special characters in double-quoted PowerShell strings). Single-quoted PowerShell strings are literal — only `'` needs escaping, doubling it to `''`. If a context requires double-quoted PS values, escape embedded `\"` as `` ` ``, backtick as `` `` ``, and `$` as `` ` `` (backtick is the PS escape character in double-quoted strings; `$` must be escaped to prevent variable expansion). On bwrap, always pass values as separate argv tokens after the `--setenv` flag (`--setenv KEY VALUE`, two tokens), never as a single concatenated `KEY=VALUE` token that an intermediate shell would interpret.\n- **Use the array-form argv for every sandbox subprocess.** Never `shell:`-interpolate. The same invariant-3 rules (`array-form spawn`, `stdin: 'ignore'`, `cwd`, `timeout`, `proc.kill()` in `finally`) apply to sandbox spawns as to any other subprocess — see the `subprocess-safety` cross-link.\n\n## Sandbox fallback parity (Windows and Linux)\n\n`sandbox\u002F{linux,macos,win32}\u002F*.ts` has primary executors plus legacy fallbacks (Windows `NativeWindowsSandboxExecutor` + `RestrictedEnvironmentExecutor` \u002F PowerShell wrapper, Linux `BubblewrapSandboxExecutor` + no-sandbox fallback). When you modify any of the following on the primary executor, you MUST update the fallback path in the same change to keep behavior parity and add a parity test:\n\n- `getEnvOverrides` signature or merge semantics.\n- `wrapCommand` scoping rules (allowed roots, read-only mounts, temp-dir allocation).\n- `isAvailable()` \u002F capability probe logic.\n- Failure-mode handling (does a missing sandbox envelope hard-fail or soft-fail to env-only isolation?).\n- Scope-materialization for lane-scoped resources.\n\nA divergence between primary and fallback that is not exercised by a parity test is a regression. The existing per-OS test files `tests\u002Funit\u002Fsandbox\u002F{linux,macos,win32}.test.ts` must continue to cover both the primary and fallback paths after every env-affecting change — extend these tests rather than relying on dedicated sandbox-envoverride test files that may or may not exist in your branch.\n\n## SAST baseline capturing (differential scanning)\n\nThe `sast_scan` tool supports `capture_baseline: true` with a `phase` parameter\nto snapshot pre-existing findings. Subsequent scans with the same `phase` value\nperform differential checking — they only fail on **new** findings, not\npre-existing ones.\n\n### When to capture a baseline\n\n- **Before Phase 1 code changes.** The baseline must reflect the state of the\n  codebase *before* any new work is done. This ensures the differential scan\n  catches findings introduced by the current session's changes.\n\n### Critical safety guard\n\n**NEVER capture a baseline after code changes have been made in a phase.**\nA baseline captured post-edit silently encodes the very bugs the scan is meant\nto catch as \"pre-existing,\" suppressing them indefinitely. This turns the SAST\ngate into theater.\n\n### How to use it\n\n1. Identify the files to scan. In a phase, use the union of declared task-scope\n   files plus files the coder is expected to touch. Derive the list from\n   `declare_scope` outputs, `git diff --name-only`, or the phase's task specs.\n2. Before any coder delegation in Phase 1, capture the baseline:\n   ```\n   sast_scan(directory, changed_files=[...], capture_baseline=true, phase=1)\n   ```\n3. After coder work, scan the same file set:\n   ```\n   sast_scan(directory, changed_files=[...], phase=1)\n   ```\n   This returns only NEW findings (absent from the baseline).\n4. If a pre-existing finding is legitimately fixed, the baseline can be\n   re-captured at the start of the next phase with the updated file list.\n\n### Why this matters\n\nDuring PR #1704 review, SAST flagged `RegExp.prototype.exec()` as\n\"command injection via child_process.exec()\" — a false positive that blocked\nthe gate. With a baseline captured before the phase, this pre-existing false\npositive would have been suppressed, and only genuinely new findings would\nsurface.\n",{"name":5,"description":7},"main","1667541871a3a917f9e544e5584ef06a544a119d",".opencode\u002Fskills\u002Fengineering-conventions",0,"https:\u002F\u002Fgithub.com\u002Fdjimit\u002Fdjimitflo","https:\u002F\u002Fgithub.com\u002Fdjimit","https:\u002F\u002Fdjimit.nl\u002F","About me\r\n\r\nI’m Dennis a strategic IT advisor specializing in cloud, cybersecurity, privacy, AI, and enterprise architecture. ","2026-11-15 04:42:36",{"source":8,"skillName":5,"commands":34,"prompt":44,"zipAvailable":45},[35,38,41],{"tool":36,"command":37},"npx","npx skills add djimit\u002Fdjimitflo --skill engineering-conventions",{"tool":39,"command":40},"bunx","bunx skills add djimit\u002Fdjimitflo --skill engineering-conventions",{"tool":42,"command":43},"pnpm","pnpm dlx skills add djimit\u002Fdjimitflo --skill engineering-conventions","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fdjimit\u002Fdjimitflo\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Fengineering-conventions\u002FSKILL.md",true,[],[48,55,62,69,76,83],{"skillNo":49,"name":50,"nameZh":6,"description":51,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":52,"categories":53,"keywords":54,"publishedAt":19},"01M732DRW7MHQP9VTJ5JSBMWC3","provider-step-usage-v1-0-0","Sum measured OpenCode step_finish token totals with replay deduplication and fail-closed validation.","https:\u002F\u002Fgithub.com\u002Fdjimit\u002Fdjimitflo\u002Fblob\u002Fmain\u002Fskills\u002Fprovider-step-usage-v1-0-0\u002FSKILL.md",[],[],{"skillNo":56,"name":57,"nameZh":6,"description":58,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":59,"categories":60,"keywords":61,"publishedAt":19},"01M732DKXHWZ1P99ZDNA4PX7BV","writing-tests","Guidelines for writing, organizing, and maintaining tests in the opencode-swarm repository. Covers framework rules (bun:test), mock isolation, CI pipeline structure, file placement, and anti-patterns that break cross-platform CI. Load this skill before writing or modifying any test file.","https:\u002F\u002Fgithub.com\u002Fdjimit\u002Fdjimitflo\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Fwriting-tests\u002FSKILL.md",[],[],{"skillNo":63,"name":64,"nameZh":6,"description":65,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":66,"categories":67,"keywords":68,"publishedAt":19},"01M732DCEG1R9S45A68T5WR2T7","worktree-retry-cleanup","Protocol for cleaning parallel-coder worktree lanes before retry. Triggered before re-dispatching any task that already has a lane (completed, denied, cancelled, or failed).","https:\u002F\u002Fgithub.com\u002Fdjimit\u002Fdjimitflo\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Fworktree-retry-cleanup\u002FSKILL.md",[],[],{"skillNo":70,"name":71,"nameZh":6,"description":72,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":73,"categories":74,"keywords":75,"publishedAt":19},"01M732D8KYWE5RHJ1AA76F70K7","swarm","Cross-agent swarm-mode behavior model — a higher-rigor workflow using parallel investigation, independent reviewer validation, and critic challenge, plus the mandatory implementation closeout gate. Runtime adapters (.claude, .agents) add execution-specific notes and command wiring.","https:\u002F\u002Fgithub.com\u002Fdjimit\u002Fdjimitflo\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Fswarm\u002FSKILL.md",[],[],{"skillNo":77,"name":78,"nameZh":6,"description":79,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":80,"categories":81,"keywords":82,"publishedAt":19},"01M732D232XCMYP3XYKEAQC3YT","swarm-pr-subscribe","Monitor a pull request after creation and act autonomously on pushed PR activity. Use when subscribing to a PR after opening it, when asked to watch, babysit, or autofix a PR until merge, or when a \u003Cpr-activity> wake message or [pr-monitor:...] advisory arrives for a subscribed PR. Owns event triage (fix \u002F ask \u002F skip), bounded-retry escalation, and terminal-state cleanup.","https:\u002F\u002Fgithub.com\u002Fdjimit\u002Fdjimitflo\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Fswarm-pr-subscribe\u002FSKILL.md",[],[],{"skillNo":84,"name":85,"nameZh":6,"description":86,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":87,"categories":88,"keywords":89,"publishedAt":19},"01M732CVKJ4QEN83DQ30EYG75A","swarm-pr-review","Run a graph-guided, tool-augmented Swarm PR review using context packing, parallel exploration, triggered plugin micro-lanes, independent reviewer validation, critic challenge, and metrics writeback. Use for deep pull request review with low false-positive tolerance and high recall.","https:\u002F\u002Fgithub.com\u002Fdjimit\u002Fdjimitflo\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Fswarm-pr-review\u002FSKILL.md",[],[]]