opencode-skills-collection 4.0.35 → 4.0.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundled-skills/.antigravity-install-manifest.json +13 -1
- package/bundled-skills/agent-evaluation-reporting/SKILL.md +136 -0
- package/bundled-skills/agent-harness-fault-injection/SKILL.md +250 -0
- package/bundled-skills/anti-ui-slop/SKILL.md +115 -0
- package/bundled-skills/audit-agent-run-evidence/SKILL.md +165 -0
- package/bundled-skills/boost-asio-pro/SKILL.md +172 -0
- package/bundled-skills/boost-asio-pro/references/build.md +88 -0
- package/bundled-skills/boost-asio-pro/references/classic-boost.md +33 -0
- package/bundled-skills/boost-asio-pro/references/coroutines.md +415 -0
- package/bundled-skills/boost-asio-pro/references/pre-cpp20.md +164 -0
- package/bundled-skills/boost-asio-pro/references/ssl.md +38 -0
- package/bundled-skills/cross-platform-contract-propagation-audit/SKILL.md +159 -0
- package/bundled-skills/docs/integrations/jetski-cortex.md +3 -3
- package/bundled-skills/docs/integrations/jetski-gemini-loader/README.md +1 -1
- package/bundled-skills/docs/maintainers/repo-growth-seo.md +1 -1
- package/bundled-skills/docs/maintainers/skills-update-guide.md +1 -1
- package/bundled-skills/docs/users/aas-core.md +9 -1
- package/bundled-skills/docs/users/bundles.md +1 -1
- package/bundled-skills/docs/users/claude-code-skills.md +1 -1
- package/bundled-skills/docs/users/gemini-cli-skills.md +1 -1
- package/bundled-skills/docs/users/kiro-integration.md +1 -1
- package/bundled-skills/docs/users/usage.md +3 -3
- package/bundled-skills/docs/users/visual-guide.md +4 -4
- package/bundled-skills/dsh-deepread/SKILL.md +200 -0
- package/bundled-skills/liuguang-banlan-ui/SKILL.md +135 -0
- package/bundled-skills/liuguang-banlan-ui/assets/starter/favicon.svg +4 -0
- package/bundled-skills/liuguang-banlan-ui/assets/starter/index.html +32 -0
- package/bundled-skills/liuguang-banlan-ui/assets/starter/launcher.css +25 -0
- package/bundled-skills/liuguang-banlan-ui/assets/starter/obsidian/index.html +179 -0
- package/bundled-skills/liuguang-banlan-ui/assets/starter/obsidian/theme-config.js +105 -0
- package/bundled-skills/liuguang-banlan-ui/assets/starter/obsidian/theme.css +107 -0
- package/bundled-skills/liuguang-banlan-ui/assets/starter/opal/index.html +179 -0
- package/bundled-skills/liuguang-banlan-ui/assets/starter/opal/theme-config.js +105 -0
- package/bundled-skills/liuguang-banlan-ui/assets/starter/opal/theme.css +107 -0
- package/bundled-skills/liuguang-banlan-ui/assets/starter/shared/base.css +423 -0
- package/bundled-skills/liuguang-banlan-ui/assets/starter/shared/spectral-field.js +450 -0
- package/bundled-skills/liuguang-banlan-ui/assets/starter/shared/workbench.js +255 -0
- package/bundled-skills/liuguang-banlan-ui/references/style-contract.md +53 -0
- package/bundled-skills/liuguang-banlan-ui/references/verification.md +70 -0
- package/bundled-skills/liuguang-banlan-ui/scripts/measure_preview.py +144 -0
- package/bundled-skills/liuguang-banlan-ui/scripts/requirements.txt +2 -0
- package/bundled-skills/liuguang-banlan-ui/scripts/scaffold_template.py +43 -0
- package/bundled-skills/liuguang-banlan-ui/scripts/validate_manifest.py +173 -0
- package/bundled-skills/multi-source-search/SKILL.md +139 -0
- package/bundled-skills/multi-source-search/references/report-schema.md +47 -0
- package/bundled-skills/multi-source-search/scripts/validate_report.py +221 -0
- package/bundled-skills/review-multi-agent-orchestration/SKILL.md +201 -0
- package/bundled-skills/ui-slop-score/SKILL.md +80 -0
- package/bundled-skills/using-lwc/LICENSE +201 -0
- package/bundled-skills/using-lwc/README.md +926 -0
- package/bundled-skills/using-lwc/README.zh-CN.md +836 -0
- package/bundled-skills/using-lwc/SKILL.md +156 -0
- package/bundled-skills/using-lwc/agents/openai.yaml +4 -0
- package/bundled-skills/using-lwc/assets/global-purpose.md +17 -0
- package/bundled-skills/using-lwc/assets/global-schema.md +28 -0
- package/bundled-skills/using-lwc/references/active-memory.md +81 -0
- package/bundled-skills/using-lwc/references/agent-onboarding.md +84 -0
- package/bundled-skills/using-lwc/references/code-graph.md +60 -0
- package/bundled-skills/using-lwc/references/core-memory.md +51 -0
- package/bundled-skills/using-lwc/references/document-conversion.md +53 -0
- package/bundled-skills/using-lwc/references/document-graph.md +58 -0
- package/bundled-skills/using-lwc/references/llm-wiki.md +75 -0
- package/bundled-skills/using-lwc/references/memory-policy.md +551 -0
- package/bundled-skills/using-lwc/references/operations-manual.md +503 -0
- package/bundled-skills/using-lwc/references/recovery-maintenance.md +53 -0
- package/bundled-skills/using-lwc/references/strong-context.md +54 -0
- package/bundled-skills/using-lwc/references/trigger-playbook.md +53 -0
- package/bundled-skills/using-lwc/references/word-graph.md +45 -0
- package/bundled-skills/using-lwc/scripts/bootstrap.sh +359 -0
- package/bundled-skills/using-lwc/scripts/install-lwc.sh +172 -0
- package/bundled-skills/youtube-summarizer/SKILL.md +21 -7
- package/bundled-skills/youtube-summarizer/scripts/extract-transcript.py +45 -12
- package/package.json +3 -2
- package/skills_index.json +268 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: audit-agent-run-evidence
|
|
3
|
+
description: "Use when an agent, harness, gateway, MCP workflow, or multi-step automation claims completion and the available traces, checkpoints, approvals, tool calls, or deployment records must be judged without trusting self-reported success."
|
|
4
|
+
risk: safe
|
|
5
|
+
source: self
|
|
6
|
+
date_added: "2026-08-19"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Audit Agent Run Evidence
|
|
10
|
+
|
|
11
|
+
## Overview
|
|
12
|
+
|
|
13
|
+
Turn an end-to-end success statement into independently decidable claims. Reconstruct what happened from available records, grade each claim against the strongest witness, and keep missing evidence distinct from failure.
|
|
14
|
+
|
|
15
|
+
This is a read-only audit. Do not rerun tools, approve actions, resume workers, deploy artifacts, or modify evidence unless the user separately authorizes those actions.
|
|
16
|
+
|
|
17
|
+
## When to Use
|
|
18
|
+
|
|
19
|
+
- Auditing a completed or interrupted agent run from traces and artifacts.
|
|
20
|
+
- Checking whether an agent's end-to-end success claim is actually supported.
|
|
21
|
+
- Reviewing MCP, gateway, sandbox, checkpoint, retry, memory, approval, or deployment evidence.
|
|
22
|
+
- Separating autonomous success from human-assisted or merely requested outcomes.
|
|
23
|
+
|
|
24
|
+
Do not use this skill to design instrumentation for a future run or to perform the missing actions. It evaluates evidence that already exists.
|
|
25
|
+
|
|
26
|
+
## Establish the Contract
|
|
27
|
+
|
|
28
|
+
Record these inputs before judging the run:
|
|
29
|
+
|
|
30
|
+
- declared goal and terminal success criteria;
|
|
31
|
+
- run, workflow, task, and parent identifiers;
|
|
32
|
+
- immutable code, configuration, model, prompt, tool-schema, and artifact revisions when available;
|
|
33
|
+
- actors and trust boundaries: orchestrator, worker, sandbox, MCP server, gateway, human approver, CI, and deployment platform;
|
|
34
|
+
- retry, deadline, token, cost, concurrency, and human-escalation budgets;
|
|
35
|
+
- supplied evidence inventory and known collection gaps.
|
|
36
|
+
|
|
37
|
+
Do not silently strengthen the original success criteria. Do not weaken them to match the evidence that happens to exist.
|
|
38
|
+
|
|
39
|
+
## Build a Claim Ledger
|
|
40
|
+
|
|
41
|
+
Split the overall claim into atomic predicates. Give every row a stable claim ID.
|
|
42
|
+
|
|
43
|
+
| Field | Required content |
|
|
44
|
+
|---|---|
|
|
45
|
+
| `claim_id` | Stable identifier |
|
|
46
|
+
| `predicate` | One falsifiable statement |
|
|
47
|
+
| `required_witness` | Source that can independently prove it |
|
|
48
|
+
| `evidence_refs` | Exact event, log, artifact, or record IDs |
|
|
49
|
+
| `counterevidence_refs` | Conflicting records |
|
|
50
|
+
| `coverage` | Required instances versus observed instances |
|
|
51
|
+
| `verdict` | `proven`, `partially_proven`, `contradicted`, or `not_proven` |
|
|
52
|
+
| `gap` | Missing field, actor, interval, or verification |
|
|
53
|
+
|
|
54
|
+
Typical predicates include:
|
|
55
|
+
|
|
56
|
+
- every required step reached its terminal postcondition;
|
|
57
|
+
- sandbox isolation held for every executing worker;
|
|
58
|
+
- each required MCP/tool call has a correlated response;
|
|
59
|
+
- retries respected idempotency and did not duplicate committed effects;
|
|
60
|
+
- a checkpoint was durably written, verified, and actually used for resume;
|
|
61
|
+
- parallel branches satisfied the declared join policy;
|
|
62
|
+
- memory reads cite a versioned source rather than an untracked summary;
|
|
63
|
+
- retry, deadline, token, cost, and escalation budgets were respected;
|
|
64
|
+
- approval was granted by an authorized human for the exact artifact and target;
|
|
65
|
+
- the platform deployed that same artifact and passed the declared health checks.
|
|
66
|
+
|
|
67
|
+
## Normalize Evidence
|
|
68
|
+
|
|
69
|
+
Preserve original records and create a normalized event view with:
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"run_id": "run-123",
|
|
74
|
+
"event_id": "evt-42",
|
|
75
|
+
"sequence": 42,
|
|
76
|
+
"observed_at": "RFC3339 timestamp",
|
|
77
|
+
"actor": {"type": "worker", "id": "worker-2"},
|
|
78
|
+
"operation": "mcp.search",
|
|
79
|
+
"state_before": "researching",
|
|
80
|
+
"state_after": "researching",
|
|
81
|
+
"attempt": 2,
|
|
82
|
+
"request_id": "req-9",
|
|
83
|
+
"idempotency_key": "task-7:search:2",
|
|
84
|
+
"input_digest": "sha256:...",
|
|
85
|
+
"output_digest": "sha256:...",
|
|
86
|
+
"checkpoint_seq": 3,
|
|
87
|
+
"parent_event_id": "evt-41",
|
|
88
|
+
"status": "succeeded",
|
|
89
|
+
"evidence_ref": "tool-log:991"
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Use `null` or `unknown` for absent values. Never synthesize IDs, timestamps, digests, costs, approvals, or outcomes.
|
|
94
|
+
|
|
95
|
+
Verify bundle hashes or signatures when supplied. Check duplicate IDs, broken parent links, non-monotonic per-source sequences, impossible state transitions, unaccounted clock skew, and unexplained trace gaps. Treat an integrity failure as counterevidence for claims that depend on the affected records.
|
|
96
|
+
|
|
97
|
+
## Rank Witnesses
|
|
98
|
+
|
|
99
|
+
Prefer the witness closest to the effect:
|
|
100
|
+
|
|
101
|
+
| Claim | Strong witness | Insufficient alone |
|
|
102
|
+
|---|---|---|
|
|
103
|
+
| Code changed | Commit/tree and diff | Agent narration |
|
|
104
|
+
| Test passed | Complete test result bound to revision | Command invocation |
|
|
105
|
+
| MCP effect occurred | Server or provider audit record | Client request |
|
|
106
|
+
| Checkpoint resumed | Durable checkpoint plus verified load event | Checkpoint file exists |
|
|
107
|
+
| Human approved | Authorization-system decision bound to artifact and target | Approval requested |
|
|
108
|
+
| Deployment succeeded | Platform record plus required health checks | Deployment started |
|
|
109
|
+
| Memory grounded a decision | Versioned memory read and citation | Final answer resembles memory |
|
|
110
|
+
|
|
111
|
+
An orchestrator and its child worker are not independent witnesses when they repeat the same unverified result. A cryptographic digest proves byte identity, not semantic correctness.
|
|
112
|
+
|
|
113
|
+
## Reconstruct the Run
|
|
114
|
+
|
|
115
|
+
1. Order events by causal links and per-source sequence; use timestamps only as supporting evidence.
|
|
116
|
+
2. Build the state-transition path and mark every gap or illegal transition.
|
|
117
|
+
3. Link each retry chain by logical operation, request ID, and idempotency key.
|
|
118
|
+
4. Link checkpoints to the state they contain and the resume event that consumes them.
|
|
119
|
+
5. Preserve every parallel branch outcome; apply the declared `all_required`, `quorum`, `first_success`, or other join rule.
|
|
120
|
+
6. Track remaining budgets at each transition. A late success after budget exhaustion is a budget violation.
|
|
121
|
+
7. Bind approvals and deployment records to exact artifact digests and targets.
|
|
122
|
+
|
|
123
|
+
Do not infer successful completion from a final state label when required intermediate predicates are missing.
|
|
124
|
+
|
|
125
|
+
## Assign Verdicts
|
|
126
|
+
|
|
127
|
+
- `proven`: authentic evidence covers every instance of the predicate and no reliable counterevidence remains.
|
|
128
|
+
- `partially_proven`: some required instances or fields are proven and the uncovered portion is named.
|
|
129
|
+
- `contradicted`: reliable evidence conflicts with the predicate.
|
|
130
|
+
- `not_proven`: evidence is absent, circular, unverifiable, or only self-reported.
|
|
131
|
+
|
|
132
|
+
Use `not_proven`, not `contradicted`, for missing logs. Use `contradicted` when the trace shows a failed health check, duplicate effect, unauthorized approver, corrupt checkpoint, skipped required branch, or exhausted budget.
|
|
133
|
+
|
|
134
|
+
The end-to-end verdict cannot be stronger than its weakest required predicate. Optional diagnostics may remain unproven without failing the run if they were never part of the declared contract.
|
|
135
|
+
|
|
136
|
+
## Report
|
|
137
|
+
|
|
138
|
+
Return sections in this order:
|
|
139
|
+
|
|
140
|
+
1. **Scope and evidence inventory** — run identity, declared criteria, records inspected, integrity checks.
|
|
141
|
+
2. **Claim ledger** — one row per predicate with verdict and exact references.
|
|
142
|
+
3. **Reconstructed timeline** — only state-changing, fault, retry, checkpoint, join, approval, and deployment events.
|
|
143
|
+
4. **Gaps and counterevidence** — identify the affected claims and whether collection can still recover the evidence.
|
|
144
|
+
5. **Overall verdict** — one sentence plus the blocking claim IDs.
|
|
145
|
+
|
|
146
|
+
Example conclusion:
|
|
147
|
+
|
|
148
|
+
> `partially_proven`: repository steps C1-C18 and checkpoint recovery C22 are proven, but deployment success is not proven because C31 has only a client-side start event and no platform health result.
|
|
149
|
+
|
|
150
|
+
## Common Mistakes
|
|
151
|
+
|
|
152
|
+
- Treating a successful process exit as proof of the business postcondition.
|
|
153
|
+
- Counting retries as separate successful logical operations.
|
|
154
|
+
- Accepting a child agent's summary as independent corroboration.
|
|
155
|
+
- Calling a checkpoint recoverable without observing a verified reload.
|
|
156
|
+
- Calling an approval request an approval grant.
|
|
157
|
+
- Reporting percentages without listing the denominator and missing instances.
|
|
158
|
+
- Recommending instrumentation as though it were evidence from the completed run.
|
|
159
|
+
|
|
160
|
+
## Limitations
|
|
161
|
+
|
|
162
|
+
- An audit cannot recover facts that no trusted source recorded.
|
|
163
|
+
- Provider logs may establish external effects without proving the agent's internal reasoning.
|
|
164
|
+
- Redaction may be necessary for secrets and personal data; record the redaction scope and preserve stable references.
|
|
165
|
+
- If evidence collection would mutate external state or expose sensitive data, stop and request authorization.
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: boost-asio-pro
|
|
3
|
+
description: "Use when writing asynchronous C++ networking code with Boost.Asio or standalone Asio — TCP/UDP servers and clients, SSL/TLS, timers, strands, composed async ops. Covers io_context, co_spawn, awaitable, async_read/async_write, asio::spawn, yield_context, and pre-C++20 callback styles."
|
|
4
|
+
category: development
|
|
5
|
+
risk: safe
|
|
6
|
+
source: community
|
|
7
|
+
source_repo: alexprivalov/boost-asio-skill
|
|
8
|
+
source_type: community
|
|
9
|
+
date_added: "2026-08-18"
|
|
10
|
+
author: alexprivalov
|
|
11
|
+
tags: [cpp, boost, asio, async, networking, coroutines]
|
|
12
|
+
tools: [claude, cursor, gemini]
|
|
13
|
+
license: "MIT"
|
|
14
|
+
license_source: "https://github.com/alexprivalov/boost-asio-skill/blob/main/LICENSE"
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# Boost.Asio / standalone Asio
|
|
18
|
+
|
|
19
|
+
## Overview
|
|
20
|
+
|
|
21
|
+
Write async C++ networking code that compiles on the *user's* Boost, not the newest one. Asio's API changed shape three times (classic `io_service` → `io_context` → C++20 coroutines) and most Asio code on the internet is from the first era, so **pick the style from the toolchain first**, then follow that style's reference file.
|
|
22
|
+
|
|
23
|
+
**References:** [Boost.Asio](https://www.boost.org/doc/libs/latest/doc/html/boost_asio.html) · [standalone Asio](https://think-async.com/Asio/)
|
|
24
|
+
|
|
25
|
+
Asio's API changed shape three times, so the same task has three correct answers depending on the Boost version in front of you. This skill makes the agent establish that version first, then apply the rules that are genuinely easy to get wrong — strand versus write serialization, buffer and connection lifetime, composed reads for framing — and finally check its own output against a list before calling it done.
|
|
26
|
+
|
|
27
|
+
## When to Use This Skill
|
|
28
|
+
|
|
29
|
+
- Use when writing or reviewing async C++ networking code with Boost.Asio or standalone Asio: TCP/UDP servers and clients, SSL/TLS streams, timers, resolvers.
|
|
30
|
+
- Use when the code involves `io_context`, `io_service`, `co_spawn`, `awaitable`, `async_read`, `async_write`, `strand`, `asio::spawn`, `yield_context`, or completion-handler callbacks.
|
|
31
|
+
- Use when the target toolchain is old: an older Boost or a pre-C++20 standard, where coroutine examples will not compile.
|
|
32
|
+
- Use when async code compiles but misbehaves: interleaved writes, dangling buffers, sockets closing early, `operation_aborted` treated as an error.
|
|
33
|
+
|
|
34
|
+
## Step 1: pick the style (do this before writing code)
|
|
35
|
+
|
|
36
|
+
Determine the Boost (or Asio) version and the C++ standard actually in use — `find_package(Boost)` output, `dpkg -l libboost-dev`, `brew info boost`, `CMAKE_CXX_STANDARD`, or ask. Do not assume the newest.
|
|
37
|
+
|
|
38
|
+
| Boost | C++ std | Style | Read |
|
|
39
|
+
|-------|---------|-------|------|
|
|
40
|
+
| ≥ 1.77 | C++20 | Coroutines (`co_await` + `awaitable<T>`) — preferred | [references/coroutines.md](references/coroutines.md) |
|
|
41
|
+
| ≥ 1.74 | C++11–17 | Completion handlers (callbacks) — the portable baseline | [references/pre-cpp20.md](references/pre-cpp20.md) |
|
|
42
|
+
| ≥ 1.80 | C++11–17 | Stackful `asio::spawn` + `yield_context` (links Boost.Coroutine — not header-only) | [references/pre-cpp20.md](references/pre-cpp20.md) |
|
|
43
|
+
| 1.62–1.65 | C++11 | Classic `io_service` / `strand.wrap` / `expires_from_now` | [references/classic-boost.md](references/classic-boost.md) |
|
|
44
|
+
|
|
45
|
+
SSL/TLS in any style: [references/ssl.md](references/ssl.md). CMake for any style: [references/build.md](references/build.md).
|
|
46
|
+
|
|
47
|
+
`io_context`, `make_strand`, `bind_executor`, `steady_timer`, `signal_set`, `async_read`/`async_write`/`async_read_until`, buffers and `resolver` are **library** features — identical in the coroutine and callback styles. Only the suspension mechanism differs.
|
|
48
|
+
|
|
49
|
+
## Step 2: version floors (verified by compiling, not from docs)
|
|
50
|
+
|
|
51
|
+
Reach for one of these and the build breaks on older distros:
|
|
52
|
+
|
|
53
|
+
| Feature | Floor |
|
|
54
|
+
|---------|-------|
|
|
55
|
+
| `experimental/awaitable_operators.hpp` (the `\|\|` / `&&` operators) | **Boost ≥ 1.77** / Asio ≥ 1.20 |
|
|
56
|
+
| `as_tuple` completion token | **Boost ≥ 1.79** / Asio ≥ 1.21 |
|
|
57
|
+
| `co_composed` (custom composed ops) | **Boost ≥ 1.85** / Asio ≥ 1.30 |
|
|
58
|
+
| 3-arg `asio::spawn(ex, fn, token)` | **Boost ≥ 1.80** (older Boost has only `spawn(ex, fn)`) |
|
|
59
|
+
| `any_io_executor` (`strand<any_io_executor>`, `tcp::socket`'s default executor) | **Boost ≥ 1.74** — the floor for the callback style; below it, use legacy `io_context::strand` |
|
|
60
|
+
| `io_context`, `make_strand`, `expires_after` | **Boost ≥ 1.66** — below it, classic `io_service` |
|
|
61
|
+
|
|
62
|
+
Distro floors that bite: **Debian bookworm ships Boost 1.74** (no `awaitable_operators.hpp` — `#include` fails outright), Ubuntu 20.04 ships 1.71 (no `any_io_executor`), Debian 9 ships 1.62.
|
|
63
|
+
|
|
64
|
+
Language, not library: the chrono literals `250ms` / `30s` are **C++14**. For a true C++11 build write `std::chrono::milliseconds(250)`.
|
|
65
|
+
|
|
66
|
+
## Step 3: the rules that are actually easy to get wrong
|
|
67
|
+
|
|
68
|
+
**A strand does not serialize writes.** A strand serializes handler *execution*, not whole composed operations. Two `async_write`s in flight on the same strand still **interleave bytes on the wire**. Full-duplex (a read loop plus concurrent pushes/replies) needs a per-connection strand **and** an outbound queue with an in-flight flag, so at most one `async_write` exists at a time. This is the single most common wrong answer about Asio.
|
|
69
|
+
|
|
70
|
+
**Buffers do not own memory.** `asio::buffer()` is a view. Storage must outlive the operation: coroutine locals are fine across `co_await` in the same frame; in callback style the same data must become a **member**, not a local.
|
|
71
|
+
|
|
72
|
+
**Connections must outlive their handlers.** `enable_shared_from_this`, and capture `self` in *every* `co_spawn` / handler — read loop, write loop, and each timer.
|
|
73
|
+
|
|
74
|
+
**Frame with composed reads.** `async_read` (fills the buffer exactly) for a length prefix and then the body; never `async_read_some`, which returns short.
|
|
75
|
+
|
|
76
|
+
**Wrap `as_tuple`.** Always `as_tuple(use_awaitable)`. Bare `as_tuple` resolves against the operation's default token and compiles in some contexts, fails in others.
|
|
77
|
+
|
|
78
|
+
**`async_accept(make_strand(...))` changes two things**: it forces an explicit completion token back on the call, and the accepted socket is `basic_stream_socket<tcp, strand<...>>`, not `tcp::socket`. Take it **by value** or with `auto` — binding it to `tcp::socket&` will not compile.
|
|
79
|
+
|
|
80
|
+
**Re-arming a timer resolves the pending wait with `operation_aborted`.** In an idle-timeout loop that is the signal to keep waiting, not an error.
|
|
81
|
+
|
|
82
|
+
**GCC needs `-fcoroutines`** for the C++20 style, and header-only Boost needs `BOOST_ERROR_CODE_HEADER_ONLY` defined in exactly one place (CMake).
|
|
83
|
+
|
|
84
|
+
## Common mistakes
|
|
85
|
+
|
|
86
|
+
| Mistake | Fix |
|
|
87
|
+
|---------|-----|
|
|
88
|
+
| Buffer dangling (local goes out of scope during async op) | Ensure buffer lifetime ≥ operation lifetime; coroutine locals or members, not callback locals |
|
|
89
|
+
| Forgetting `io.run()` | No handlers dispatch without `run()` / `run_one()` |
|
|
90
|
+
| Concurrent socket access without strand | Wrap in `strand<>` or serialize via one coroutine chain |
|
|
91
|
+
| Assuming a strand prevents interleaved writes | Add a write queue — see Step 3 |
|
|
92
|
+
| Using `use_awaitable` where `deferred` suffices | Omit the token (default is `deferred`) unless using `\|\|` / `&&` |
|
|
93
|
+
| Ignoring short reads/writes | Use composed `async_read` / `async_write` / `async_read_until`, not `async_read_some` |
|
|
94
|
+
| Not setting `reuse_address` on the acceptor | Set before `bind`/`listen` or restarts hit "address in use" |
|
|
95
|
+
| SSL operations without a strand | *All* `ssl::stream` ops need strand synchronization |
|
|
96
|
+
| Blocking inside a handler | Never block in a completion handler |
|
|
97
|
+
| Accepting a socket with the wrong executor type | See `async_accept(make_strand(...))` in Step 3 |
|
|
98
|
+
| Requiring the `Boost::system` component | Header-only since 1.74: `Boost::headers` + `BOOST_ERROR_CODE_HEADER_ONLY`. Only classic (pre-1.66) needs the link |
|
|
99
|
+
| Missing `-fcoroutines` on GCC | Build fails — add `$<$<CXX_COMPILER_ID:GNU>:-fcoroutines>` |
|
|
100
|
+
| Writing coroutine code for a Boost that predates it | Do Step 1 first |
|
|
101
|
+
|
|
102
|
+
## Boost.Asio vs standalone Asio
|
|
103
|
+
|
|
104
|
+
Same author, same API — namespace and includes differ.
|
|
105
|
+
|
|
106
|
+
| Aspect | Boost.Asio | Standalone Asio |
|
|
107
|
+
|--------|-----------|-----------------|
|
|
108
|
+
| Namespace / include | `boost::asio` / `<boost/asio.hpp>` | `asio` / `<asio.hpp>` |
|
|
109
|
+
| Error code | `boost::system::error_code` | `asio::error_code` (or `std::error_code`) |
|
|
110
|
+
| Install (brew) | `brew install boost` | `brew install asio` |
|
|
111
|
+
| CMake | `Boost::headers` | manual include path |
|
|
112
|
+
| Version (2025) | 1.87–1.90 (with Boost) | 1.30–1.36 (independent) |
|
|
113
|
+
| Macro prefix | `BOOST_ASIO_` | `ASIO_` |
|
|
114
|
+
|
|
115
|
+
Support both with a shim, then use `net::` throughout:
|
|
116
|
+
```cpp
|
|
117
|
+
#ifdef USE_STANDALONE_ASIO
|
|
118
|
+
#include <asio.hpp>
|
|
119
|
+
namespace net = asio;
|
|
120
|
+
using error_code = asio::error_code;
|
|
121
|
+
#else
|
|
122
|
+
#include <boost/asio.hpp>
|
|
123
|
+
namespace net = boost::asio;
|
|
124
|
+
using error_code = boost::system::error_code;
|
|
125
|
+
#endif
|
|
126
|
+
namespace ssl = net::ssl;
|
|
127
|
+
using tcp = net::ip::tcp;
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Before you call it done
|
|
131
|
+
|
|
132
|
+
Check the code you just wrote against this list:
|
|
133
|
+
|
|
134
|
+
- [ ] Style matches the target Boost version and C++ standard (Step 1), and every API used clears its floor (Step 2).
|
|
135
|
+
- [ ] Every buffer passed to an async op outlives that op — no callback locals, no dangling `string_view`.
|
|
136
|
+
- [ ] At most one `async_write` per socket in flight, enforced by a queue + flag, if anything writes concurrently with reading.
|
|
137
|
+
- [ ] Every async chain on a shared object runs on the same strand; `self` captured in every handler and `co_spawn`.
|
|
138
|
+
- [ ] Framing / delimited reads use composed `async_read` / `async_read_until`.
|
|
139
|
+
- [ ] Errors are handled, not swallowed: `as_tuple(use_awaitable)` destructured, or the callback's `ec` checked, on every op.
|
|
140
|
+
- [ ] `operation_aborted` distinguished from real errors wherever a timer is re-armed or an op is cancelled.
|
|
141
|
+
- [ ] Acceptor sets `reuse_address`; shutdown path closes the acceptor and drains sessions.
|
|
142
|
+
- [ ] CMake has the standard, `-fcoroutines` for GCC (C++20 only), `BOOST_ERROR_CODE_HEADER_ONLY` in one place, and `Boost::coroutine` only if using stackful `spawn`.
|
|
143
|
+
- [ ] It compiles. Build it — most of the mistakes above are compile-time, and the version floors are only real once tested.
|
|
144
|
+
|
|
145
|
+
## Worked examples
|
|
146
|
+
|
|
147
|
+
Three CI-verified implementations of the same full-duplex framed-protocol server, one per style — copy from the one matching Step 1. Paths are relative to this skill directory; if only the skill was installed, they are at https://github.com/alexprivalov/boost-asio-skill/tree/main/examples.
|
|
148
|
+
|
|
149
|
+
- `../../examples/market-data-feed/` — C++20 coroutines (Boost 1.77+; verified 1.83–1.90)
|
|
150
|
+
- `../../examples/market-data-feed-precpp20/` — callbacks, C++11-clean (verified Boost 1.74+, incl. Windows/MSVC)
|
|
151
|
+
- `../../examples/market-data-feed-classic/` — classic `io_service` (verified back to Boost 1.62 / Debian 9)
|
|
152
|
+
|
|
153
|
+
## Official documentation
|
|
154
|
+
|
|
155
|
+
- Overview: https://www.boost.org/doc/libs/latest/doc/html/boost_asio/overview.html
|
|
156
|
+
- Reference: https://www.boost.org/doc/libs/latest/doc/html/boost_asio/reference.html
|
|
157
|
+
- Examples: https://www.boost.org/doc/libs/latest/doc/html/boost_asio/examples.html
|
|
158
|
+
|
|
159
|
+
## Limitations
|
|
160
|
+
|
|
161
|
+
- This skill does not replace compiling and testing against the target toolchain. The version floors it documents are only real once built — build the code.
|
|
162
|
+
- It does not cover Boost.Beast (HTTP/WebSocket), io_uring backends, or UDP multicast specifics.
|
|
163
|
+
- Stop and ask when the Boost version and C++ standard cannot be determined; the style choice depends on them.
|
|
164
|
+
|
|
165
|
+
## Security & Safety Notes
|
|
166
|
+
|
|
167
|
+
- Read-only guidance: this skill contains no shell commands, network fetches, credentials, or mutation instructions. The commands it names (`dpkg -l libboost-dev`, `brew info boost`) are local version queries.
|
|
168
|
+
- Networking code it produces accepts untrusted input. Validate length prefixes before allocating (`std::string body(n, 0)` with an attacker-controlled `n` is a memory-exhaustion vector — cap it), and verify peer certificates when using TLS rather than disabling verification to make a handshake pass.
|
|
169
|
+
|
|
170
|
+
## Related Skills
|
|
171
|
+
|
|
172
|
+
- `@cpp-pro` — general modern C++ idioms; this skill assumes them and adds the Asio-specific rules.
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Build Configuration
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Boost.Asio (header-only since Boost 1.74+)
|
|
5
|
+
|
|
6
|
+
```cmake
|
|
7
|
+
find_package(Boost REQUIRED)
|
|
8
|
+
find_package(OpenSSL REQUIRED) # if using SSL
|
|
9
|
+
find_package(Threads REQUIRED)
|
|
10
|
+
|
|
11
|
+
target_link_libraries(myapp PRIVATE
|
|
12
|
+
Boost::headers # header-only Asio
|
|
13
|
+
OpenSSL::SSL OpenSSL::Crypto # if using SSL
|
|
14
|
+
Threads::Threads
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
target_compile_features(myapp PRIVATE cxx_std_20)
|
|
18
|
+
|
|
19
|
+
# REQUIRED for GCC coroutine support — build will fail without this
|
|
20
|
+
target_compile_options(myapp PRIVATE
|
|
21
|
+
$<$<CXX_COMPILER_ID:GNU>:-fcoroutines>
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
# Optional: truly header-only (no Boost.System link needed)
|
|
25
|
+
target_compile_definitions(myapp PRIVATE BOOST_ERROR_CODE_HEADER_ONLY)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Standalone Asio (always header-only)
|
|
29
|
+
|
|
30
|
+
```cmake
|
|
31
|
+
# Standalone Asio has no CMake config — use pkg-config or manual path
|
|
32
|
+
find_package(OpenSSL REQUIRED)
|
|
33
|
+
find_package(Threads REQUIRED)
|
|
34
|
+
|
|
35
|
+
# If installed via brew:
|
|
36
|
+
find_path(ASIO_INCLUDE_DIR asio.hpp HINTS /opt/homebrew/include)
|
|
37
|
+
|
|
38
|
+
target_include_directories(myapp PRIVATE ${ASIO_INCLUDE_DIR})
|
|
39
|
+
target_link_libraries(myapp PRIVATE OpenSSL::SSL OpenSSL::Crypto Threads::Threads)
|
|
40
|
+
target_compile_features(myapp PRIVATE cxx_std_20)
|
|
41
|
+
target_compile_definitions(myapp PRIVATE ASIO_STANDALONE)
|
|
42
|
+
|
|
43
|
+
target_compile_options(myapp PRIVATE
|
|
44
|
+
$<$<CXX_COMPILER_ID:GNU>:-fcoroutines>
|
|
45
|
+
)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Dual-mode CMake (supports both)
|
|
49
|
+
|
|
50
|
+
```cmake
|
|
51
|
+
option(USE_STANDALONE_ASIO "Use standalone Asio instead of Boost.Asio" OFF)
|
|
52
|
+
|
|
53
|
+
find_package(OpenSSL REQUIRED)
|
|
54
|
+
find_package(Threads REQUIRED)
|
|
55
|
+
|
|
56
|
+
if(USE_STANDALONE_ASIO)
|
|
57
|
+
find_path(ASIO_INCLUDE_DIR asio.hpp HINTS /opt/homebrew/include)
|
|
58
|
+
target_include_directories(myapp PRIVATE ${ASIO_INCLUDE_DIR})
|
|
59
|
+
target_compile_definitions(myapp PRIVATE USE_STANDALONE_ASIO ASIO_STANDALONE)
|
|
60
|
+
else()
|
|
61
|
+
find_package(Boost REQUIRED)
|
|
62
|
+
target_link_libraries(myapp PRIVATE Boost::headers)
|
|
63
|
+
target_compile_definitions(myapp PRIVATE BOOST_ERROR_CODE_HEADER_ONLY)
|
|
64
|
+
endif()
|
|
65
|
+
|
|
66
|
+
target_link_libraries(myapp PRIVATE OpenSSL::SSL OpenSSL::Crypto Threads::Threads)
|
|
67
|
+
target_compile_features(myapp PRIVATE cxx_std_20)
|
|
68
|
+
target_compile_options(myapp PRIVATE $<$<CXX_COMPILER_ID:GNU>:-fcoroutines>)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Header-Only Usage
|
|
72
|
+
|
|
73
|
+
**Boost.Asio:** Asio is header-only by default. The only thing that pulls in a Boost library to link is `boost::system::error_code`'s out-of-line symbols, so for a truly link-free build define **`BOOST_ERROR_CODE_HEADER_ONLY`**. `BOOST_ASIO_HEADER_ONLY` is rarely needed and only relevant if separate compilation was previously enabled; you do **not** normally need both.
|
|
74
|
+
|
|
75
|
+
**Define `BOOST_ERROR_CODE_HEADER_ONLY` in exactly ONE place — prefer CMake** (`target_compile_definitions`, as shown above). Defining it in CMake *and* with a source `#define` triggers `-Wmacro-redefined`. So in source, just include — no `#define`:
|
|
76
|
+
```cpp
|
|
77
|
+
#include <boost/asio.hpp>
|
|
78
|
+
#include <boost/asio/ssl.hpp>
|
|
79
|
+
#include <boost/asio/experimental/awaitable_operators.hpp>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**Standalone Asio:**
|
|
83
|
+
```cpp
|
|
84
|
+
#include <asio.hpp>
|
|
85
|
+
#include <asio/ssl.hpp>
|
|
86
|
+
#include <asio/experimental/awaitable_operators.hpp>
|
|
87
|
+
// No macros needed — always header-only
|
|
88
|
+
```
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Classic Boost (pre-1.66, the `io_service` era — verified to 1.62)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
To support Boost older than 1.66 (no `io_context`, no `make_strand`, no `any_io_executor`), drop to the classic API — verified building **back to Boost 1.62** (Debian 9) while still compiling on current Boost via a tiny shim:
|
|
5
|
+
|
|
6
|
+
| Modern (1.66+) | Classic (pre-1.66) |
|
|
7
|
+
|----------------|--------------------|
|
|
8
|
+
| `io_context` | `io_service` |
|
|
9
|
+
| `make_strand(ex)` / `strand<any_io_executor>` | `io_service::strand strand(io)` |
|
|
10
|
+
| `bind_executor(strand, h)` | `strand.wrap(h)` |
|
|
11
|
+
| `timer.expires_after(d)` | `timer.expires_from_now(d)` |
|
|
12
|
+
| move-return `async_accept()` | `async_accept(socket_, handler)` |
|
|
13
|
+
| header-only `error_code` | link **Boost.System** (`find_package(Boost COMPONENTS system)`) |
|
|
14
|
+
|
|
15
|
+
Only the `io_service`/`io_context` name and the `expires_after`/`expires_from_now` call actually differ across 1.62…1.90 — isolate both behind `#if BOOST_VERSION >= 106600`:
|
|
16
|
+
```cpp
|
|
17
|
+
#include <boost/version.hpp>
|
|
18
|
+
#include <boost/asio/steady_timer.hpp> // not pulled in by <boost/asio.hpp> on old Boost
|
|
19
|
+
#if BOOST_VERSION >= 106600
|
|
20
|
+
using io_service_t = boost::asio::io_context;
|
|
21
|
+
#else
|
|
22
|
+
using io_service_t = boost::asio::io_service;
|
|
23
|
+
#endif
|
|
24
|
+
template <class T, class Rep, class Period>
|
|
25
|
+
void timer_expires_in(T& t, std::chrono::duration<Rep,Period> d) {
|
|
26
|
+
#if BOOST_VERSION >= 106600
|
|
27
|
+
t.expires_after(d);
|
|
28
|
+
#else
|
|
29
|
+
t.expires_from_now(d);
|
|
30
|
+
#endif
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
CMake for this range: `cmake_minimum_required(VERSION 3.5)` (Debian 9 ships cmake 3.7), link `Boost::system` only if the component is found (modern Boost is header-only and has no such component), and use the classic out-of-source build (`mkdir build && cd build && cmake ..`) since `-S`/`-B` need cmake ≥ 3.13.
|