Skip to content

Commit 7e58dfe

Browse files
wchilders-nvidiadaveedvdv-nvidia
authored andcommitted
Initial work on an AGENTS.md file and associated skills []
1 parent d6518a9 commit 7e58dfe

11 files changed

Lines changed: 897 additions & 1 deletion

File tree

‎.agents/README.md‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Portable agent skills
2+
3+
Project skills live here in the open
4+
[Agent Skills](https://agentskills.io/) format. Each subdirectory contains a
5+
`SKILL.md` with YAML frontmatter (`name`, `description`) and instructions.
6+
7+
```
8+
.agents/skills/<skill-name>/SKILL.md
9+
```
10+
11+
Do not add parallel copies under tool-specific paths (`.cursor/skills/`,
12+
`.claude/skills/`, etc.); keep a single tree under `.agents/skills/`.
13+
14+
Always-on project guidance for all agents: [`AGENTS.md`](../AGENTS.md) at the
15+
repository root. Changelog encoding: skill `edg-changes-example`.
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
---
2+
name: acknowledg-bench
3+
description: >-
4+
Reads Cachegrind .cgout Ir totals, compares benchmark baselines to runs,
5+
and supports AcknowlEDG bench review / update-baseline flows. Use when
6+
editing edg-bench-run-delta, edgacknowledg.client.bench, .cgout summary
7+
parsing, or benchmark UI ops fields.
8+
---
9+
10+
# AcknowlEDG / Cachegrind benchmarks
11+
12+
## Metric
13+
14+
**Ir** (instruction reads) is the first `summary:` integer in a `.cgout`.
15+
CLIs and the UI call it **OPs**. Lower run Ir vs baseline = faster.
16+
17+
```text
18+
events: Ir I1mr ILmr Dr ...
19+
...
20+
summary: 3696685 6148 4719 ...
21+
```
22+
23+
With cache-sim enabled there are multiple counts; **always use the first**
24+
(Ir). Do not sum fields or take a later column.
25+
26+
Shared regex (keep both call sites in sync):
27+
28+
```python
29+
_REGEX_CGOUT_SUMMARY = re.compile(r'^summary: ([0-9]+)(?: [0-9]+)*\n$')
30+
```
31+
32+
## Readers
33+
34+
| Location | Function |
35+
| --- | --- |
36+
| [`dev_tools/bin/edg-bench-run-delta`](../../../dev_tools/bin/edg-bench-run-delta) | `read_program_totals` |
37+
| [`dev_tools/pylibs/edgacknowledg/client/bench/__init__.py`](../../../dev_tools/pylibs/edgacknowledg/client/bench/__init__.py) | same |
38+
39+
Readers scan the last ~10 lines for `summary:`. Missing/malformed → skip that
40+
benchmark. Do not invent a third independent parser.
41+
42+
Percent change:
43+
44+
```text
45+
((baseline - run) / max(1, baseline)) * 100
46+
```
47+
48+
## Layout
49+
50+
Bench home: `$EDG_BENCH_HOME` or `<repo>/benchmarks`.
51+
52+
| Path | Role |
53+
| --- | --- |
54+
| `benchmarks/benchmarks/**/*.bnch.cpp` | Sources |
55+
| `benchmarks/runs/<YYYY.MM.DD-HH.MM.SS>/…/*.bnch.cgout` | Runs |
56+
| `benchmarks/baselines/project/<tag>/` | Project baselines |
57+
| `benchmarks/baselines/user/<name>/` | User baselines (`@name` tag) |
58+
| `benchmarks/.acknowledg-cache/` | `cg_annotate` disk cache |
59+
60+
Relative `.cgout` paths must exist under both run and baseline dirs to compare.
61+
62+
## Review / UI principles
63+
64+
Wire payloads should carry raw `baseline_ops` / `run_ops` (and baseline tag
65+
when needed). Derive in the client:
66+
67+
- op delta, percent change, faster/slower badges
68+
- mean / median / population stdev over the list
69+
- sort order
70+
71+
Do **not** ship redundant counts, samples arrays, or precomputed change
72+
comments when the UI already has the ops list.
73+
74+
Bench annotate detail uses `cg_annotate --no-annotate --diff` (delta output,
75+
not a line-oriented source diff).
76+
77+
## Update baseline
78+
79+
Bench editor copies the selected run `.cgout` into the session’s baseline tag
80+
directory and refreshes statuses (`BenchEditHandler` /
81+
`edg-bench-review`).
82+
83+
## Protocol
84+
85+
Tags `bench.src.*` / `bench.edit.*`: see
86+
[PROTOCOL.md](../../../dev_tools/services/acknowledg/PROTOCOL.md).
87+
Client architecture: skill **acknowledg-client**.
88+
Python under `dev_tools/`: skill **edg-python-style**.
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
---
2+
name: acknowledg-client
3+
description: >-
4+
Works on the AcknowlEDG Python client: BatchClient vs DirectClient,
5+
ReviewClient Protocol, resilient websocket reconnect, and test/bench
6+
provider handlers. Use when editing edgacknowledg.client, edgy-review,
7+
edg-bench-review, edg-acknowledg-cli, or section subscribe/reconnect logic.
8+
---
9+
10+
# AcknowlEDG client
11+
12+
Canonical package: [`dev_tools/pylibs/edgacknowledg/`](../../../dev_tools/pylibs/edgacknowledg/).
13+
`dev_tools/services/acknowledg/server/edgacknowledg` is a **symlink** — edit
14+
pylibs only.
15+
16+
Wire protocol (tags, routes, auth, occupancy):
17+
[PROTOCOL.md](../../../dev_tools/services/acknowledg/PROTOCOL.md). Keep
18+
`PROTOCOL_REVISION` in sync with
19+
`dev_tools/services/acknowledg/client/src/sockets.js`.
20+
21+
## Public API
22+
23+
From `edgacknowledg.client` (`__all__`):
24+
25+
- `BatchClient` / `DirectClient` — async context managers; constructor takes
26+
endpoint settings and optional `status_listener`
27+
- `BatchClientSession` / `DirectClientSession` — yielded by client `__aenter__`;
28+
`create_review` / `remove_review`, `close()`, `stopped()`, `start()`, `stop()`
29+
(client `__aexit__` awaits `stopped()` then `stop()`)
30+
- `ConnectionStatusListener` — `connected` / `attempting_reconnect` /
31+
`disconnected`
32+
- `ReviewClient` (structural **Protocol**): `review_id`, `name`, `timestamp`,
33+
`sections()`, `add_section` / `remove_section`
34+
- URL/env helpers: `add_endpoint_arguments`, `form_section_http_url`,
35+
`default_*` host/port helpers
36+
- Shared: `BackgroundWorkerPool`, errors
37+
38+
Usage:
39+
40+
```python
41+
async with BatchClient(
42+
api_host=..., api_port=..., status_listener=listener
43+
) as session:
44+
review = await session.create_review(...)
45+
# Block ends when session.stop() is called, or on cancellation.
46+
```
47+
48+
Private (leading `_`): `_ClientReview`, `_BatchClientReview`,
49+
`_DirectClientReview`, channel helpers. Callers should type against
50+
`ReviewClient`, not private classes.
51+
52+
## Batch vs Direct
53+
54+
| | Batch | Direct |
55+
| --- | --- | --- |
56+
| Socket | One resilient `/batch` | Per-section `/source|edit/<uuid>/<kind>/<slug>` |
57+
| Mux | `batch.subscribe` / `unsubscribe` / `event` | Dedicated WS per section |
58+
| CLI | `edg-acknowledg-cli` | `edgy-review`, `edg-bench-review` |
59+
| Reconnect | Drop local subs, `_restore_subscriptions()` | Each section's `ResilientWebsocket` loop |
60+
61+
Direct URL mapping uses handler `subscription_type` (e.g. `test.src` →
62+
`/source/.../test/<slug>`, `bench.edit` → `/edit/.../bench/<slug>`).
63+
64+
## Reconnect
65+
66+
[`client/websocket.py`](../../../dev_tools/pylibs/edgacknowledg/client/websocket.py):
67+
`ResilientWebsocket`, exponential backoff + jitter on connect failure;
68+
jitter-only delay after a drop. Pattern:
69+
70+
```python
71+
async for websocket in ResilientWebsocket(...):
72+
try:
73+
...
74+
except ConnectionClosed:
75+
continue
76+
```
77+
78+
Auth header: `X-AcknowlEDG-API-Key` (never put the key in query strings).
79+
`RoleOccupied`: discard that handler / stop reconnecting that section; keep
80+
other sections running.
81+
82+
## Batch subscription maps
83+
84+
`_BatchClientReview` tracks:
85+
86+
- `_subscriptions: Dict[int, uuid.UUID]` — `id(handler)` → server subscription id
87+
- `_subscription_tasks: Dict[uuid.UUID, asyncio.Task]` — subscription id → task
88+
89+
Unsubscribe needs the server id; the handler-key map provides it after
90+
reconnect bookkeeping.
91+
92+
## Providers
93+
94+
| Package | Handlers |
95+
| --- | --- |
96+
| `client/test/__init__.py` | `TestSourceHandler` (`test.src`), `TestEditHandler` (`test.edit`) |
97+
| `client/bench/__init__.py` | `BenchSourceHandler` (`bench.src`), `BenchEditHandler` (`bench.edit`) |
98+
99+
Shared: `ReviewClientHandler`, `Channel`, `announce_section`,
100+
`trunc_display_content` in `client/shared.py`.
101+
102+
## Env / URLs
103+
104+
- `EDG_ACKNOWLEDG_API_{HOST,PORT}`, `EDG_ACKNOWLEDG_UI_{HOST,PORT}`,
105+
`EDG_ACKNOWLEDG_API_KEY`
106+
- Defaults: API `localhost:2727`, UI `localhost:5173`; non-localhost hosts
107+
default port 80
108+
- Print UI section URLs as soon as the section exists (`form_section_http_url`)
109+
- Timestamps: `utc_now_iso` / `is_iso_timestamp` — no `Z` / `+00:00` munging
110+
111+
## Python style here
112+
113+
Follow skill **edg-python-style** (2-space indent, ` = ` in kwargs,
114+
`f"..."` / `'...'`, match neighbors).
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
---
2+
name: edg-changes-example
3+
description: >-
4+
Encodes and decodes non-UTF-8 example bytes in Changes changelogs with
5+
edg-changes-example («HHHH...» markers) and writes Changes files as UTF-8.
6+
Use when editing any Changes file (src/Changes, util/Changes, …), adding
7+
examples with Latin-1/EUC-JP/Shift-JIS/other non-UTF-8 bytes, or verifying
8+
changelog encoding.
9+
---
10+
11+
# `edg-changes-example` and Changes files
12+
13+
## Policy (all `Changes` files)
14+
15+
Any path named `Changes` under the monorepo (for example `src/Changes`,
16+
`util/Changes`, `lib_src/Changes`, `include_c++/Changes`, `nt_util/Changes`)
17+
must remain **valid UTF-8** on disk.
18+
19+
- Write and save Changes entries as **UTF-8**.
20+
- Ordinary Unicode that is valid UTF-8 may appear as real characters (or as
21+
C/C++ escapes such as `\u00b6` in examples). Do **not** wrap valid UTF-8
22+
in `«…»` unless you intentionally need a raw-byte example
23+
(`encode --escape-all-non-ascii`).
24+
- Examples that need **non-UTF-8** bytes (legacy Latin-1, EUC-JP, Shift-JIS,
25+
etc.) must use `«HHHH…»` markers produced by `edg-changes-example`, never
26+
raw non-UTF-8 bytes in the committed file.
27+
28+
CLI: `dev_tools/bin/edg-changes-example` (on `PATH` when direnv is active).
29+
30+
## Note line (required for encoded examples)
31+
32+
When an entry’s example contains one or more `«…»` hex markers, add this
33+
note on its own line after the example, matching existing changelog style:
34+
35+
```text
36+
Note: The above example must be decoded using the edg-changes-example tool.
37+
```
38+
39+
Use that exact wording. Place it immediately after the example block (blank
40+
line before the next dated entry is fine).
41+
42+
## Encode (raw → UTF-8 Changes text)
43+
44+
Given a fragment or file that still contains raw non-UTF-8 bytes:
45+
46+
```bash
47+
edg-changes-example encode raw-fragment.txt > utf8-fragment.txt
48+
# or:
49+
edg-changes-example encode -o utf8-fragment.txt raw-fragment.txt
50+
printf '...' | edg-changes-example encode
51+
```
52+
53+
Default encode keeps maximal runs of bytes `>= 0x80` that form valid UTF-8,
54+
and replaces only non-UTF-8 runs with one marker `«` + hex + `»` (two hex
55+
digits per byte, no separators). `\uXXXX` in the text is left alone.
56+
57+
Optional: `--escape-all-non-ascii` escapes every byte `>= 0x80`, including
58+
valid UTF-8 sequences (rare; only when the example must show raw bytes).
59+
60+
## Decode (UTF-8 Changes text → raw bytes)
61+
62+
To rebuild the real example bytes (for local reproduction, not for commit):
63+
64+
```bash
65+
edg-changes-example decode utf8-fragment.txt > raw-fragment.txt
66+
edg-changes-example decode -o raw-fragment.txt utf8-fragment.txt
67+
# Whole file:
68+
edg-changes-example decode src/Changes > /tmp/Changes.raw
69+
```
70+
71+
Decode replaces each `«HHHH…»` (or legacy `«HH»«HH»`) with the corresponding
72+
bytes. No other escapes are interpreted.
73+
74+
## Workflow for a new changelog entry
75+
76+
1. Draft the entry as UTF-8 prose.
77+
2. If an example needs non-UTF-8 bytes, author the example in a small raw
78+
file (or produce the markers by hand only when the bytes are already
79+
known), then run `edg-changes-example encode` and paste the UTF-8 result
80+
into the entry.
81+
3. Immediately after that example, add:
82+
83+
`Note: The above example must be decoded using the edg-changes-example tool.`
84+
85+
4. Insert the entry into the appropriate `Changes` file with a **UTF-8**
86+
write (keep the rest of the file valid UTF-8).
87+
5. Verify the file still decodes as UTF-8 (raises on failure):
88+
89+
```bash
90+
python3 -c "open('path/to/Changes', encoding='utf-8').read()"
91+
```
92+
93+
Use the real path (for example `src/Changes`). A clean exit means the
94+
whole file is valid UTF-8; a `UnicodeDecodeError` means the write
95+
introduced non-UTF-8 bytes and must be fixed before continuing.
96+
97+
## Do not
98+
99+
- Commit raw Latin-1 / Shift-JIS / etc. bytes inside a `Changes` file.
100+
- Invent alternate note wording; match the existing sentence above.
101+
- Run `encode` on the entire historical `src/Changes` and rewrite it unless
102+
that is an explicit, reviewed task — encode **new example fragments**, then
103+
splice the UTF-8 text into the entry.
104+
105+
## Related
106+
107+
Always-on summary: [AGENTS.md](../../../AGENTS.md). Front-end context:
108+
skill **edg-cpfe-frontend**.
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
---
2+
name: edg-cpfe-bisect
3+
description: >-
4+
Finds the commit that introduced a test regression or improved behavior
5+
between known good and bad front-end revisions using
6+
edg-docker-test-bisect (and edg-bisect for manual steps). Use when
7+
troubleshooting a failing or newly-passing test across two commits,
8+
searching for the first bad commit, or locating a fix commit.
9+
---
10+
11+
# EDG cpfe test bisection
12+
13+
Prefer Docker. Put `dev_tools/bin` on `PATH` (direnv /
14+
[HACKING.md](../../../HACKING.md)). Project root = directory containing
15+
`src/cfe.c` and `dev_tools/`.
16+
17+
Full tutorial: [dev_annex/tutorials/TEST_BISECT.md](../../../dev_annex/tutorials/TEST_BISECT.md).
18+
Build/test/record recipes: skill **edg-cpfe-build-test**.
19+
20+
## When to use
21+
22+
You need a **test that differs** between two revisions, plus:
23+
24+
| Goal | Newer tip | Older tip |
25+
| --- | --- | --- |
26+
| Find the **regressing** commit | bad (fails) | good (passes) |
27+
| Find the **fixing** commit | good (passes) | bad (fails) |
28+
29+
The CLI detects which situation you mean after verifying that the test
30+
behaves differently on the two commits.
31+
32+
## Automatic bisect
33+
34+
Canonical CLI: **`edg-docker-test-bisect`** (not `edg-docker-bisect`).
35+
36+
```bash
37+
edg-docker-test-bisect [--posture POSTURE] <bad_commit> <good_commit> <test_path>
38+
```
39+
40+
- **Overwrites** front-end sources during the run; restores them to **HEAD**
41+
afterward (HEAD itself is not rewritten as history).
42+
- Tip: `--posture=quick-c-fe` for speed (C-generating `edg_x86_64` only).
43+
44+
### Test path forms
45+
46+
- `sandbox/foo.sft.cpp` (short form; preferred)
47+
- `tests/sandbox/foo.sft.cpp`
48+
- `tests/tests/sandbox/foo.sft.cpp`
49+
- Or a cwd-relative / absolute path into a valid suite
50+
51+
If the reproducer is throwaway, put it under `sandbox`.
52+
53+
## Manual bisect
54+
55+
Wrapper around git-bisect style steps: `edg-bisect`
56+
(`start|good|bad|skip|reset|…`). Use when automatic mode is too heavy or you
57+
need to mark skips yourself.
58+
59+
## Checklist
60+
61+
1. Confirm the test **fails on bad** and **passes on good** (or the inverse
62+
for a fix hunt) with `edg-docker-test --non-interactive …`.
63+
2. Run `edg-docker-test-bisect` with those commits and the test path.
64+
3. After it finishes, sources should match **HEAD**; verify with `git status`.
65+
4. Inspect the identified commit; do not commit or push unless asked.

0 commit comments

Comments
 (0)