@qvac/harness 0.2.7 → 0.2.9
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/dist/harness.bundle +70 -16
- package/dist/prebuilds-manifest.json +8 -0
- package/dist-lib/index.d.ts +2 -1
- package/dist-lib/index.js +60 -59
- package/dist-lib/lib/audio-transcode-bare.js +2 -2
- package/dist-lib/lib/capabilities/completion.d.ts +35 -2
- package/dist-lib/lib/capabilities/completion.js +114 -48
- package/dist-lib/lib/capabilities/download.js +2 -2
- package/dist-lib/lib/capabilities/speech-text.js +1 -1
- package/dist-lib/lib/capabilities/tool-prompt-log.js +1 -1
- package/dist-lib/lib/capabilities/tool-selection.js +2 -2
- package/dist-lib/lib/capabilities/tool-turns.js +1 -1
- package/dist-lib/lib/capabilities/usage-breakdown.js +1 -1
- package/dist-lib/lib/capabilities/voice.js +3 -3
- package/dist-lib/lib/connect.js +12 -11
- package/dist-lib/lib/context-window.js +1 -1
- package/dist-lib/lib/contract-types.d.ts +1 -0
- package/dist-lib/lib/docx/index.js +3 -3
- package/dist-lib/lib/hardware/capability-probe.js +3 -3
- package/dist-lib/lib/hardware/gpu-probe-addon.js +2 -2
- package/dist-lib/lib/hardware/gpu-probe-entry.js +1 -1
- package/dist-lib/lib/helpers/markup-stream-filter.js +1 -1
- package/dist-lib/lib/helpers/run-outcome.js +1 -1
- package/dist-lib/lib/helpers/spawn-path.d.ts +1 -1
- package/dist-lib/lib/helpers/thinking.js +2 -2
- package/dist-lib/lib/helpers/tool-intent.js +1 -1
- package/dist-lib/lib/helpers/tool-label.js +3 -3
- package/dist-lib/lib/hooks/built-in/arg-repair.d.ts +1 -1
- package/dist-lib/lib/hooks/built-in/arg-repair.js +1 -1
- package/dist-lib/lib/hooks/built-in/egress.d.ts +1 -1
- package/dist-lib/lib/hooks/built-in/egress.js +2 -2
- package/dist-lib/lib/hooks/built-in/index.js +3 -3
- package/dist-lib/lib/hooks/built-in/skill-catalog.d.ts +1 -1
- package/dist-lib/lib/hooks/pipeline.js +4 -4
- package/dist-lib/lib/hooks/registry.js +1 -1
- package/dist-lib/lib/hooks/run.js +1 -1
- package/dist-lib/lib/models/model-catalog.js +4 -4
- package/dist-lib/lib/models/model-delete.js +1 -1
- package/dist-lib/lib/models/model-handle.js +1 -1
- package/dist-lib/lib/models/model-list.js +1 -1
- package/dist-lib/lib/models/model-pool.js +8 -8
- package/dist-lib/lib/models/model-source.js +1 -1
- package/dist-lib/lib/models/music-catalog.d.ts +1 -1
- package/dist-lib/lib/no-redirect-fetch-bare.js +3 -3
- package/dist-lib/lib/no-redirect-fetch-impl.js +1 -1
- package/dist-lib/lib/no-redirect-fetch-node.js +2 -2
- package/dist-lib/lib/resolution-detector.js +1 -1
- package/dist-lib/lib/sdk-loader.js +2 -2
- package/dist-lib/lib/sdk-storage.js +1 -1
- package/dist-lib/lib/serve.js +11 -10
- package/dist-lib/lib/spawn.js +3 -3
- package/dist-lib/lib/staging.js +1 -1
- package/dist-lib/lib/tools/catalog.js +1 -1
- package/dist-lib/lib/tools/create-documents.js +2 -2
- package/dist-lib/lib/tools/edit-documents.js +2 -2
- package/dist-lib/lib/tools/edit-image.js +2 -2
- package/dist-lib/lib/tools/exec/adapters/python/attachments.js +2 -2
- package/dist-lib/lib/tools/exec/adapters/python/create-effect.js +1 -1
- package/dist-lib/lib/tools/exec/adapters/python/loader.js +1 -1
- package/dist-lib/lib/tools/exec/adapters/python/memfs.js +2 -2
- package/dist-lib/lib/tools/exec/adapters/python/pyodide.js +6 -6
- package/dist-lib/lib/tools/exec/adapters/python/python-adapter.js +3 -3
- package/dist-lib/lib/tools/exec/adapters/python/run-session.js +5 -5
- package/dist-lib/lib/tools/exec/adapters/python/wheels.js +1 -1
- package/dist-lib/lib/tools/exec/adapters/python/worker/client.js +3 -3
- package/dist-lib/lib/tools/exec/adapters/python/worker/entry.js +4 -4
- package/dist-lib/lib/tools/exec/adapters/shell/shell-adapter.js +1 -1
- package/dist-lib/lib/tools/exec/obsidian/cli-process.js +2 -2
- package/dist-lib/lib/tools/exec/obsidian/cli.js +4 -4
- package/dist-lib/lib/tools/exec/obsidian/command.js +1 -1
- package/dist-lib/lib/tools/exec/obsidian/route.js +7 -7
- package/dist-lib/lib/tools/exec/obsidian/vault-create.js +2 -2
- package/dist-lib/lib/tools/exec/obsidian/vault-fs.js +6 -6
- package/dist-lib/lib/tools/exec/obsidian/vault-paths.js +2 -2
- package/dist-lib/lib/tools/exec/obsidian/vault-read.js +1 -1
- package/dist-lib/lib/tools/exec/obsidian/vault-write.js +2 -2
- package/dist-lib/lib/tools/exec/runner.js +1 -1
- package/dist-lib/lib/tools/exec.js +13 -13
- package/dist-lib/lib/tools/file-glob.js +3 -3
- package/dist-lib/lib/tools/fs/local.js +1 -1
- package/dist-lib/lib/tools/fs/remote.js +1 -1
- package/dist-lib/lib/tools/fs/walk.js +2 -2
- package/dist-lib/lib/tools/generate-image.js +4 -4
- package/dist-lib/lib/tools/generate-music.js +6 -6
- package/dist-lib/lib/tools/grep.js +6 -6
- package/dist-lib/lib/tools/http-request/truncate-response.js +1 -1
- package/dist-lib/lib/tools/http-request.js +9 -9
- package/dist-lib/lib/tools/mcp/utils.js +1 -1
- package/dist-lib/lib/tools/mcp-call.js +8 -8
- package/dist-lib/lib/tools/operations/builders.d.ts +1 -1
- package/dist-lib/lib/tools/operations/builders.js +1 -1
- package/dist-lib/lib/tools/operations/compile.js +1 -1
- package/dist-lib/lib/tools/operations/manifest.d.ts +16 -16
- package/dist-lib/lib/tools/operations/manifest.js +1 -1
- package/dist-lib/lib/tools/outbound-guard.js +1 -1
- package/dist-lib/lib/tools/rag-search.js +1 -1
- package/dist-lib/lib/tools/read-files.js +3 -3
- package/dist-lib/lib/tools/skill.js +8 -8
- package/dist-lib/lib/tools/skills/auth-resolver.js +2 -2
- package/dist-lib/lib/tools/skills/bin-check.js +1 -1
- package/dist-lib/lib/tools/skills/bundled-dir.js +2 -2
- package/dist-lib/lib/tools/skills/catalog.js +10 -10
- package/dist-lib/lib/tools/skills/cli-schema-check.js +1 -1
- package/dist-lib/lib/tools/skills/cli-schema-load.js +1 -1
- package/dist-lib/lib/tools/skills/cli-schema.js +4 -4
- package/dist-lib/lib/tools/skills/credential-check.js +3 -3
- package/dist-lib/lib/tools/skills/credential-grants.js +1 -1
- package/dist-lib/lib/tools/skills/credential-health.js +2 -2
- package/dist-lib/lib/tools/skills/frontmatter-parser.js +1 -1
- package/dist-lib/lib/tools/skills/index.js +5 -5
- package/dist-lib/lib/tools/skills/mention.js +1 -1
- package/dist-lib/lib/tools/skills/overlay-crud.js +1 -1
- package/dist-lib/lib/tools/skills/setup-routes.js +1 -1
- package/dist-lib/lib/tools/skills/skill-settings.js +1 -1
- package/dist-lib/lib/tools/skills/skill-state-constants.d.ts +8 -8
- package/dist-lib/lib/tools/skills/skill-state.js +9 -9
- package/dist-lib/lib/tools/toolsets.d.ts +1 -1
- package/dist-lib/lib/tools/url-guard.js +2 -2
- package/dist-lib/lib/tools/weather-lookup/place.d.ts +11 -0
- package/dist-lib/lib/tools/weather-lookup/place.js +152 -0
- package/dist-lib/lib/tools/weather-lookup/report.d.ts +37 -0
- package/dist-lib/lib/tools/weather-lookup/report.js +56 -0
- package/dist-lib/lib/tools/weather-lookup.d.ts +8 -0
- package/dist-lib/lib/tools/weather-lookup.js +110 -0
- package/dist-lib/lib/tools/web-fetch.js +10 -10
- package/dist-lib/lib/tools/web-search.js +2 -2
- package/dist-lib/lib/transport.js +1 -1
- package/dist-lib/lib/validating-lookup.js +1 -1
- package/dist-lib/lib/web-fetch/embedded-state.js +1 -1
- package/dist-lib/lib/web-fetch/extract.js +1 -1
- package/dist-lib/lib/web-fetch/images.js +1 -1
- package/dist-lib/lib/web-fetch/video.js +1 -1
- package/dist-lib/lib/web-search/engine-registry.js +7 -7
- package/dist-lib/lib/web-search/engines/aol.js +3 -3
- package/dist-lib/lib/web-search/engines/bing.js +4 -4
- package/dist-lib/lib/web-search/engines/brave.js +2 -2
- package/dist-lib/lib/web-search/engines/duckduckgo.js +3 -3
- package/dist-lib/lib/web-search/engines/google.js +4 -4
- package/dist-lib/lib/web-search/engines/wikipedia.js +2 -2
- package/dist-lib/lib/web-search/engines/yahoo.js +3 -3
- package/dist-lib/lib/web-search/fetch-html.js +1 -1
- package/dist-lib/lib/web-search/merge-results.js +1 -1
- package/dist-lib/lib/web-search/orchestrator.js +3 -3
- package/dist-lib/lib/wire.js +28 -0
- package/dist-lib/schema/baseline.js +1 -1
- package/dist-lib/schema/build.js +3 -3
- package/dist-lib/schema/harness.js +5 -2
- package/dist-lib/schema/release-tags.d.ts +2 -1
- package/dist-lib/schema/release-tags.js +9 -7
- package/dist-lib/spec/hrpc/messages.js +22 -7
- package/dist-lib/spec/hyperschema/index.js +22 -7
- package/dist-lib/spec/hyperschema/schema.json +14 -1
- package/dist-lib/spec/hyperschema/types.d.ts +3 -2
- package/package.json +21 -8
- package/worker/harness-sidecar.mjs +2 -0
- package/.claude/skills/asana/SKILL.md +0 -86
- package/.claude/skills/gh-stack/SKILL.md +0 -181
- package/.claude/skills/gh-stack/references/commands.md +0 -177
- package/.claude/skills/gh-stack/references/stack-design.md +0 -97
- package/.claude/skills/gh-stack/references/troubleshooting.md +0 -159
- package/.claude/skills/js-house-style/SKILL.md +0 -671
- package/.claude/skills/kvcache/SKILL.md +0 -171
- package/.claude/skills/pr-create/SKILL.md +0 -180
- package/.claude/skills/pr-review/SKILL.md +0 -217
- package/CLAUDE.md +0 -39
- package/docs/decisions/2026-05-29-kvcache-tool-turns.md +0 -75
- package/docs/decisions/2026-06-02-kvcache-tool-turns-reenabled.md +0 -127
- package/docs/decisions/2026-06-23-android-cpu-llm-defaults.md +0 -126
- package/docs/decisions/2026-07-29-assistant-owned-storage-layout.md +0 -88
- package/docs/decisions/2026-08-04-sidecar-orphan-reaping.md +0 -79
- package/docs/decisions/2026-08-11-pyodide-worker-thread.md +0 -68
- package/docs/decisions/2026-08-17-harness-hook-pipeline.md +0 -84
- package/docs/decisions/2026-08-17-harness-outbound-egress-guard.md +0 -176
- package/docs/decisions/2026-08-20-chat-prompt-prefix-is-stable.md +0 -95
- package/docs/decisions/2026-08-20-kvcache-static-placement.md +0 -109
- package/docs/decisions/2026-08-21-vendored-python-wheels.md +0 -85
- package/docs/decisions/2026-08-26-exec-is-not-gated-by-skills.md +0 -64
- package/docs/decisions/2026-08-27-writable-skills-overlay.md +0 -56
- package/docs/decisions/2026-09-01-skill-operation-manifests.md +0 -53
- package/docs/decisions/2026-09-01-usage-breakdown-is-measured.md +0 -78
- package/docs/decisions/2026-09-03-usage-breakdown-reported-by-the-harness.md +0 -136
- package/docs/decisions/INDEX.md +0 -38
- package/docs/decisions/TEMPLATE.md +0 -32
- package/docs/kvcache-reference.md +0 -655
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: kvcache
|
|
3
|
-
description: Reason about the QVAC SDK KV cache, the context window and ContextOverflow in @qvac/harness — including why the sliding window (n_discarded) and dynamic tools (toolsMode) were retired. Use when touching prompt-cache keys, the overflow ladder, TTFT regressions, context-overflow errors, cache invalidation on retry/regenerate, or when debugging "the model forgot the conversation". Read this BEFORE proposing any caller-side history eviction.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# KV cache + context window
|
|
7
|
-
|
|
8
|
-
Read **[docs/kvcache-reference.md](../../../docs/kvcache-reference.md)** — how it
|
|
9
|
-
works and the rules for using it. The summary below is just enough to stop the
|
|
10
|
-
common wrong turns.
|
|
11
|
-
|
|
12
|
-
This repo owns the cache: `lib/capabilities/completion.ts` (the `kvCache` key,
|
|
13
|
-
the round loop, the overflow ladder), `lib/context-window.ts`,
|
|
14
|
-
`lib/models/kv-cache.ts` and `lib/models/model-pool.ts`. The _prompt_ side —
|
|
15
|
-
folding a chat's history so it fits — is `@qvac/core → lib/compaction.ts`;
|
|
16
|
-
see its **compaction** skill before proposing anything that shrinks history.
|
|
17
|
-
|
|
18
|
-
## The one thing to internalise
|
|
19
|
-
|
|
20
|
-
Three state sets exist and are **never reconciled**:
|
|
21
|
-
|
|
22
|
-
| Layer | State | Keyed by |
|
|
23
|
-
| --------------------- | ---------------------------------------------------- | --------------- |
|
|
24
|
-
| caller (`@qvac/core`) | message **list** (shrinks only on an overflow retry) | chat |
|
|
25
|
-
| SDK | message **count** (`savedCount`) | cache file path |
|
|
26
|
-
| addon | token **positions** (`nPast`) + the on-disk `.bin` | cache key |
|
|
27
|
-
|
|
28
|
-
Almost every bug here is drift between those three, not context pressure.
|
|
29
|
-
`savedCount` means "already sent", never "still resident": nothing below the
|
|
30
|
-
SDK reports what it evicted. That is what made the retired sliding window and
|
|
31
|
-
dynamic-tools trim fatal, and it is the test for any new eviction idea.
|
|
32
|
-
|
|
33
|
-
## The knobs (two)
|
|
34
|
-
|
|
35
|
-
- `history`: the full history goes to `completion()`; the SDK computes the delta.
|
|
36
|
-
- `cacheKey: 'chat-<chatId>'` — set by the caller, consumed here at
|
|
37
|
-
[lib/capabilities/completion.ts](../../../lib/capabilities/completion.ts).
|
|
38
|
-
An accepted diagram repair primes under a child of it (`chat-<chatId>/r<n>`),
|
|
39
|
-
so deleting the chat key reclaims every generation.
|
|
40
|
-
|
|
41
|
-
Nothing else. `n_discarded` and `toolsMode` are gone from the stack, not just
|
|
42
|
-
unset.
|
|
43
|
-
|
|
44
|
-
**No client-side token math, ever.** Use the SDK's real `cacheTokens` /
|
|
45
|
-
`promptTokens` / `generatedTokens` from `completion()` stats, and react to the
|
|
46
|
-
typed `ContextOverflowError`. Never estimate chars-per-token, never reserve a
|
|
47
|
-
response budget. To A/B the cache, drop `cacheKey` locally.
|
|
48
|
-
|
|
49
|
-
If you encounter `RESERVED_FOR_RESPONSE`, a chars-per-token estimator,
|
|
50
|
-
`windowHistoryToFit`, or `toolsThatFit` anywhere, that is retired code — not the
|
|
51
|
-
shipping path, and none of it should come back.
|
|
52
|
-
|
|
53
|
-
## Retired knobs
|
|
54
|
-
|
|
55
|
-
Both were dropped on 2026-08-20 and have since been deleted upstream. Kept here
|
|
56
|
-
as bug shapes, not as options.
|
|
57
|
-
|
|
58
|
-
- **Sliding window (`n_discarded`).** SDK 0.19 dropped it from the `loadModel`
|
|
59
|
-
schema (rejected at validation) and addon 0.48 removed sliding outright. Why
|
|
60
|
-
it had to go: a slide was invisible to the SDK — it recorded the turn's full
|
|
61
|
-
message count and next sent `history.slice(savedCount)`, so the discarded span
|
|
62
|
-
was gone from the KV, never re-sent, and the model silently lost the middle of
|
|
63
|
-
the chat. While sliding was possible the tool block also travelled with every
|
|
64
|
-
turn (`toolBlockEvictable`, ~331 tokens for a 4-tool agent). A full window is
|
|
65
|
-
now a normal end state, recovered by the ladder and by the caller's fold.
|
|
66
|
-
- **Dynamic tools (`toolsMode: 'dynamic'`).** SDK 0.18 deleted the key (its
|
|
67
|
-
parser rejects it); the addon dropped `tools_compact` after 0.39.4. It was a
|
|
68
|
-
no-op on every shipped model — the addon gate is exact-arch `qwen3`, ours are
|
|
69
|
-
`qwen35`/`qwen36` — while the SDK still sliced as-if-dynamic: the previous
|
|
70
|
-
answer was duplicated into the KV every turn and, on a cold cache, only the
|
|
71
|
-
last exchange was sent instead of overflowing. Static placement is the only
|
|
72
|
-
mode: `history.slice(savedCount)`, full history on a cold cache at TTFT cost
|
|
73
|
-
only, which is also what makes the overflow ladder effective.
|
|
74
|
-
|
|
75
|
-
Full history: [2026-08-20-kvcache-static-placement](https://github.com/tetherto/qvac-app/blob/main/docs/decisions/2026-08-20-kvcache-static-placement.md),
|
|
76
|
-
still in `tetherto/qvac-app`.
|
|
77
|
-
|
|
78
|
-
## Hard facts that trip people up
|
|
79
|
-
|
|
80
|
-
- **A slice at or above `ctx_size` can never be admitted.** Nothing is decoded
|
|
81
|
-
yet, so there is nothing to evict — and nothing evicts anyway.
|
|
82
|
-
- **Overflow is a normal end state:** every long chat legitimately reaches ctx,
|
|
83
|
-
recovered by the ladder and by the caller's fold for any window at or above
|
|
84
|
-
4,096. Also legitimate: the current prompt alone exceeds ctx, a tool result
|
|
85
|
-
alone exceeds ctx, or a device that has never run this chat getting the whole
|
|
86
|
-
history (the cache is **device-local**). Anything else is a drift bug.
|
|
87
|
-
- **A thrown overflow keeps the cache** (SDK 0.19,
|
|
88
|
-
[qvac#4163](https://github.com/tetherto/qvac/pull/4163)): a prefill
|
|
89
|
-
`ContextOverflowError` or an addon pre-mutation refusal releases the turn and
|
|
90
|
-
the committed `.bin` survives. What still destroys it: a turn that hits the
|
|
91
|
-
ceiling **mid-generation** (addon `stopReason=contextOverflow`, surfaced as
|
|
92
|
-
`length`) is not committed — its file is unlinked and the next turn
|
|
93
|
-
cold-primes from history.
|
|
94
|
-
- **The tool block is not in the primed prefix** (since 0.17.1): the prime is
|
|
95
|
-
the system prompt alone. The block travels with the first turn that renders it
|
|
96
|
-
(the SDK requires a user message before believing it landed) and is skipped
|
|
97
|
-
once `toolBlockCached` is recorded at commit. It is never trimmed back out, so
|
|
98
|
-
`configHash` hashes the system prompt **plus the full tool definitions** — any
|
|
99
|
-
tool-set, description, or parameter change re-keys the file and costs a cold
|
|
100
|
-
prime. A skill activation and a `disabledToolsets` edit each do that once and
|
|
101
|
-
then hold. The block is NOT a fixed size — it is whatever the agent's
|
|
102
|
-
`enabledTools` serializes to; read `round start { tools }` and
|
|
103
|
-
`round stats { promptTokens }` from the harness log, never assume a figure.
|
|
104
|
-
- **`modelId` is identity-by-config**: `sha256(type:src:sortedConfig)[:16]`. ANY
|
|
105
|
-
`modelConfig` field change — including `verbosity` from `QVAC_LLM_VERBOSITY` —
|
|
106
|
-
is a new `modelId`, a new cache directory, and a cold prime for every chat.
|
|
107
|
-
Debug the cache with `QVAC_HARNESS_LOG`/`xxd`, never by raising addon
|
|
108
|
-
verbosity. The system prompt is NOT in `modelId` (it is in `configHash`, the
|
|
109
|
-
file name): a prompt edit cold-primes one chat, a config edit cold-primes all.
|
|
110
|
-
- **The addon compacts reasoning out of the KV itself.**
|
|
111
|
-
`remove_thinking_from_context` defaults to `true` (addon 0.33.0); since 0.48 it
|
|
112
|
-
rewinds to the block boundary and re-decodes what it keeps. `cacheTokens`
|
|
113
|
-
after a turn excludes thinking, so nothing above has to strip it.
|
|
114
|
-
- **`ContextOverflowError` carries sizes** (0.19): `requiredTokens`, `ctxSize`,
|
|
115
|
-
`cachedTokens` on the warm guard, and `promptTokens` only when the guard
|
|
116
|
-
counted tokens. The harness matches the error by `name` (`CONTEXT_OVERFLOW`)
|
|
117
|
-
and reads none of them.
|
|
118
|
-
|
|
119
|
-
## Before proposing caller-side eviction
|
|
120
|
-
|
|
121
|
-
Ask whether the SDK cache would already handle it. The answer is yes for
|
|
122
|
-
ordinary history growth; the cases that genuinely need handling above the SDK
|
|
123
|
-
are a message (or tool result) larger than `ctx_size`, plus the cross-device
|
|
124
|
-
cold start. Anything else is re-implementing the cache badly.
|
|
125
|
-
|
|
126
|
-
**Compaction is the one sanctioned exception, and it already exists in
|
|
127
|
-
`@qvac/core` — do not build a second one here.** It evicts from the prompt,
|
|
128
|
-
never from the KV; it uses the SDK's own `cacheTokens` rather than token math;
|
|
129
|
-
and it invalidates the chat key when a fold lands. The floor is
|
|
130
|
-
`COMPACTION_MIN_CTX_SIZE` (4,096): below it a fold cannot pay for the ~420-token
|
|
131
|
-
prefix it shares the window with, so those chats stay on the ladder here.
|
|
132
|
-
|
|
133
|
-
## Debugging
|
|
134
|
-
|
|
135
|
-
- `round stats { round, wallMs, TTFT, TPS, cacheTokens, promptTokens }` and
|
|
136
|
-
`round start { round, turns, tools }` — the per-round `hlog` in
|
|
137
|
-
[lib/capabilities/completion.ts](../../../lib/capabilities/completion.ts).
|
|
138
|
-
`cacheTokens` dropping back to system-prompt size mid-chat = a re-prime.
|
|
139
|
-
`turns` shrinking across an overflow with an identical outcome = an inert
|
|
140
|
-
ladder.
|
|
141
|
-
- SDK `logMessagesToAddon` tags: `PROMPT_SEND` / `CACHE_INIT` / `NO_CACHE`. A
|
|
142
|
-
`CACHE_INIT` mid-chat is a re-prime.
|
|
143
|
-
- No addon line reports eviction any more: `discarded N tokens`,
|
|
144
|
-
`[ContextSlider]` and `runtimeStats().contextSlides` left with sliding in
|
|
145
|
-
addon 0.48. A log that shows them is an old build.
|
|
146
|
-
- Cache files: `{kvCacheDir}/{cacheKey}/{modelId}/{configHash}.bin`. Two files
|
|
147
|
-
under one chat key means `configHash` changed — a volatile system prompt costs
|
|
148
|
-
one cold prime per turn.
|
|
149
|
-
|
|
150
|
-
## Versions — check these first
|
|
151
|
-
|
|
152
|
-
**This behaviour is version-specific and has changed before.** Start every task
|
|
153
|
-
here:
|
|
154
|
-
|
|
155
|
-
```bash
|
|
156
|
-
grep '"@qvac/sdk"' package.json
|
|
157
|
-
grep '"version"' node_modules/@qvac/inference/package.json node_modules/@qvac/llm-llamacpp/package.json
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
This repo pins **`@qvac/sdk` 0.19.0** → **`@qvac/inference` 0.19.0** →
|
|
161
|
-
**`@qvac/llm-llamacpp` 0.49.1**. Since 0.19 `@qvac/sdk` is a thin re-export over
|
|
162
|
-
`@qvac/inference`, and the `#sdk` import seam resolves to `@qvac/inference`
|
|
163
|
-
in-process on Bare — so the cache code that runs is
|
|
164
|
-
`node_modules/@qvac/inference/dist/plugins/builtin/llamacpp-completion/ops/`
|
|
165
|
-
(`completion-stream.js`, `kv-cache-session.js`, `context-overflow.js`), not
|
|
166
|
-
anything under `@qvac/sdk/dist`. If the shipped numbers move past these, re-read
|
|
167
|
-
before acting.
|
|
168
|
-
|
|
169
|
-
Whenever you re-verify something, update the Versions section in
|
|
170
|
-
[docs/kvcache-reference.md](../../../docs/kvcache-reference.md) in the same
|
|
171
|
-
commit.
|
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: pr-create
|
|
3
|
-
description: Write the title, body and commits for a pull request in @qvac/harness, and decide the conventional-commit type for a change — `fix` is reserved for user-facing defects in a released version. Use when opening a PR here, splitting work into a stack, or choosing between `fix` and `chore`.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# PR creation
|
|
7
|
-
|
|
8
|
-
`@qvac/harness` is a published package. The log is the only durable record of intent,
|
|
9
|
-
and for this repo it is also the changelog a consumer reads before upgrading.
|
|
10
|
-
|
|
11
|
-
## Title
|
|
12
|
-
|
|
13
|
-
```
|
|
14
|
-
type(scope): subject
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
Imperative, lowercase after the colon, no trailing period. Scope optional, and
|
|
18
|
-
only when it narrows something real. What and why, not how.
|
|
19
|
-
|
|
20
|
-
```
|
|
21
|
-
feat: publish the sidecar entry, so spawning it needs no bundle
|
|
22
|
-
fix(publish): repoint dynamic imports at dist-lib too
|
|
23
|
-
refactor: own the schema codegen tooling
|
|
24
|
-
chore: regenerate the schema
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
There is no ticket prefix here, and no title validator in CI. That is not
|
|
28
|
-
licence to be loose: nothing will catch a bad title but a reviewer.
|
|
29
|
-
|
|
30
|
-
## Types
|
|
31
|
-
|
|
32
|
-
```
|
|
33
|
-
build chore ci docs style refactor perf test fix feat
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
**`fix` is reserved for a defect a consumer of a released version could hit.**
|
|
37
|
-
It is the line someone reads to decide whether to upgrade, so it claims real
|
|
38
|
-
breakage in something already published.
|
|
39
|
-
|
|
40
|
-
| The change | Type |
|
|
41
|
-
| ----------------------------------------------------------- | -------------------------------------------------- |
|
|
42
|
-
| Breaks a consumer on a published version | `fix` |
|
|
43
|
-
| Repairs code that has never shipped (same release cycle) | `chore` |
|
|
44
|
-
| Repairs the build, the bundle, or what lands in the tarball | `build` or `fix` if a published artifact was wrong |
|
|
45
|
-
| Repairs CI, a workflow, an action pin | `ci` |
|
|
46
|
-
| Repairs or adds a test | `test` |
|
|
47
|
-
| Repairs a lint/type error | `chore` |
|
|
48
|
-
| Pure move or rename, no behaviour change | `refactor` |
|
|
49
|
-
| New capability, new export, new flag | `feat` |
|
|
50
|
-
| README, comments, docs | `docs` |
|
|
51
|
-
|
|
52
|
-
When a repair is on unreleased code, check the last release tag: if the bug was
|
|
53
|
-
never in a published version, it is `chore`, not `fix`.
|
|
54
|
-
|
|
55
|
-
Never relabel a real defect as `chore` to make the log quieter, and never
|
|
56
|
-
inflate a cleanup into `fix` to make it look urgent.
|
|
57
|
-
|
|
58
|
-
## Scopes
|
|
59
|
-
|
|
60
|
-
Optional, and taken from what the diff actually touches — `lib`, `worker`, `schema`, `spec`, `scripts`, `test`, `ci`, `publish`, or a capability name (`completion`, `tools`, `models`).
|
|
61
|
-
A scope that restates the type (`fix(fix)`) or names the whole repo adds
|
|
62
|
-
nothing; leave it off.
|
|
63
|
-
|
|
64
|
-
## Decision records
|
|
65
|
-
|
|
66
|
-
`docs/decisions/` holds the durable, non-obvious choices — why a boundary is
|
|
67
|
-
where it is, why an approach was rejected. They are reference for a future
|
|
68
|
-
reader, **not rules, and not to be loaded by default**.
|
|
69
|
-
|
|
70
|
-
Add one when this PR settles something a later reader would otherwise have to
|
|
71
|
-
reverse-engineer from the diff: a runtime or storage boundary, a wire-format or
|
|
72
|
-
schema choice, a build or publish constraint, a rejected alternative that will
|
|
73
|
-
look obvious later. Do not add one for a bug fix, a rename, or anything the code
|
|
74
|
-
already says plainly.
|
|
75
|
-
|
|
76
|
-
Copy `docs/decisions/TEMPLATE.md`, give it a `status`, list it once in
|
|
77
|
-
`INDEX.md`, and name it in the PR's Decisions section. `node
|
|
78
|
-
scripts/docs-audit.cjs` checks all of that, and CI runs it.
|
|
79
|
-
|
|
80
|
-
An **active** record may cite only paths that exist here; a path in another
|
|
81
|
-
repository is written `@qvac/harness → lib/x.ts` so the audit treats it as
|
|
82
|
-
context rather than a local file. A superseded record is exempt — it describes
|
|
83
|
-
how things used to be.
|
|
84
|
-
|
|
85
|
-
### One PR, one type
|
|
86
|
-
|
|
87
|
-
The commits carry conventional-commit types, so the mix of types _is_ the scope
|
|
88
|
-
statement. `feat:`, `fix:` and `chore:` on one branch is not a well-rounded
|
|
89
|
-
change, it is three changes sharing a branch, and a reviewer has to hold all
|
|
90
|
-
three while judging any one of them.
|
|
91
|
-
|
|
92
|
-
List them before writing the body:
|
|
93
|
-
|
|
94
|
-
```bash
|
|
95
|
-
git log --format='%s' main..HEAD | grep -oE '^[a-z]+' | sort -u
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
- **One type** is the PR's type.
|
|
99
|
-
- **A dominant type plus its own tests or docs** (`feat` + `test`, `fix` +
|
|
100
|
-
`docs`) is fine; the dominant one wins.
|
|
101
|
-
- **Unrelated types** means split the PR, or stack it.
|
|
102
|
-
|
|
103
|
-
## Small PRs, stacked
|
|
104
|
-
|
|
105
|
-
A PR is read by a human, so it has to fit in one head. Default to one concern.
|
|
106
|
-
When a change decomposes into dependent steps, do not grow one PR to fit them —
|
|
107
|
-
stack them, so each step is reviewable alone and lands in order.
|
|
108
|
-
|
|
109
|
-
- A large refactor belongs on a `refactor/...` branch with `refactor:` commits.
|
|
110
|
-
- **Refactor commits never live inside a non-refactor branch.** A `feat/` branch
|
|
111
|
-
that also reshuffles unrelated code is two PRs. Behaviour changes and pure
|
|
112
|
-
moves are reviewed differently, and mixing them hides both.
|
|
113
|
-
- A pure rename or move lands _before_ the change that depends on it, as its own
|
|
114
|
-
commit or its own PR in the stack.
|
|
115
|
-
|
|
116
|
-
Branch names must never contain `codex`, `cursor`, or `claude` (case
|
|
117
|
-
insensitive). Use a neutral name before committing or pushing.
|
|
118
|
-
|
|
119
|
-
## Body
|
|
120
|
-
|
|
121
|
-
`.github/pull_request_template.md` pre-fills the headings. Keep its shape, fill
|
|
122
|
-
what applies, and delete the sections that would be empty — an absent section
|
|
123
|
-
says more than one saying "n/a". The template's own order is Why, What, Testing,
|
|
124
|
-
Decisions; the expanded form below is what each should contain.
|
|
125
|
-
|
|
126
|
-
```markdown
|
|
127
|
-
## What
|
|
128
|
-
|
|
129
|
-
One paragraph. The change, in the reviewer's terms.
|
|
130
|
-
|
|
131
|
-
## Why
|
|
132
|
-
|
|
133
|
-
The problem this solves, or the decision it implements. Link the issue,
|
|
134
|
-
PR, or upstream change that forced it.
|
|
135
|
-
|
|
136
|
-
## How
|
|
137
|
-
|
|
138
|
-
Only the parts a reader would not infer from the diff: the seam that moved,
|
|
139
|
-
the invariant being preserved, the thing that looks wrong but isn't.
|
|
140
|
-
|
|
141
|
-
## Testing
|
|
142
|
-
|
|
143
|
-
What you ran, and what it proved. ``bun run test` (node, bare and addon lanes)` at minimum.
|
|
144
|
-
Say plainly when something could not be tested locally and why.
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
For a **breaking change**, say so in the body under its own `## Breaking`
|
|
148
|
-
heading, with the migration a consumer has to perform. Published package —
|
|
149
|
-
this is the only warning they get.
|
|
150
|
-
|
|
151
|
-
## Before opening
|
|
152
|
-
|
|
153
|
-
1. Check the branch is not `main` and the name is neutral.
|
|
154
|
-
2. `git log --oneline main..HEAD` — every commit is a conventional commit, and
|
|
155
|
-
each one is a change you would defend on its own. A trail of `wip`,
|
|
156
|
-
`fixup` or `address review` commits is not history; reshape it before
|
|
157
|
-
opening.
|
|
158
|
-
3. `bun run lint` and ``bun run test` (node, bare and addon lanes)` pass locally. CI runs the same lanes; a
|
|
159
|
-
red PR wastes a reviewer's round trip.
|
|
160
|
-
4. Rebase on `main` rather than merging it in. A merge commit in the branch
|
|
161
|
-
makes the diff unreadable.
|
|
162
|
-
5. Open as a **draft** unless you are asking for review right now.
|
|
163
|
-
|
|
164
|
-
```bash
|
|
165
|
-
gh pr create --repo tetherto/qvac-harness --draft --title "type(scope): subject" --body-file <path>
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
Never push to `main`, never force-push a branch someone else is reviewing, and
|
|
169
|
-
never open a PR that carries commits you did not write without saying so.
|
|
170
|
-
|
|
171
|
-
## Version bumps
|
|
172
|
-
|
|
173
|
-
Release PRs in this repo are titled by version alone (`0.2.4 (#32)`,
|
|
174
|
-
`release/0.1.4 (#40)`). They carry the version bump and nothing else — do not
|
|
175
|
-
fold a bump into a feature PR, and do not fold a feature into a bump.
|
|
176
|
-
|
|
177
|
-
## Sibling skills
|
|
178
|
-
|
|
179
|
-
- Reviewing a PR or a local diff → **pr-review**.
|
|
180
|
-
- How the code itself should be shaped → **js-house-style**.
|
|
@@ -1,217 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: pr-review
|
|
3
|
-
description: Deep-dive review of a pull request in @qvac/harness, or of local uncommitted/branch changes when invoked with `local`. Checks CI, the commit type and title, code quality against the house style, contract and API mismatches, and missing tests. In PR mode it creates PENDING inline comments only after the user confirms them, and never submits the review event. In local mode it prints findings in chat and posts nothing. Use when reviewing a PR, given a PR link, or asked to review the working tree or current branch.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# PR review
|
|
7
|
-
|
|
8
|
-
Reviews changes in `@qvac/harness`. Two modes.
|
|
9
|
-
|
|
10
|
-
- **PR mode** (a PR number or URL) — a short overview in chat, then a **pending**
|
|
11
|
-
GitHub review of per-file inline comments. The pending review is created only
|
|
12
|
-
after the user confirms the exact set of comments. **Never submit the review
|
|
13
|
-
event** (`COMMENT`, `REQUEST_CHANGES`, `APPROVE`) — that is the user's call,
|
|
14
|
-
from the GitHub UI.
|
|
15
|
-
- **Local mode** (`local`, or "review my changes") — the overview in chat only.
|
|
16
|
-
Posts nothing, anywhere.
|
|
17
|
-
|
|
18
|
-
## Reviewing is read-only
|
|
19
|
-
|
|
20
|
-
This skill never writes to the working tree. Against the user's repo these are
|
|
21
|
-
forbidden, whatever the reason:
|
|
22
|
-
|
|
23
|
-
- `git switch`, `git checkout`, `git reset`, `git restore`, `git clean`
|
|
24
|
-
- `git stash`, in any form
|
|
25
|
-
- `git pull`, `git merge`, `git rebase`, `git cherry-pick`
|
|
26
|
-
- `gh pr checkout`
|
|
27
|
-
- any edit to a file
|
|
28
|
-
|
|
29
|
-
Local mode reads the diff with `git diff`, `git status` and `git ls-files`, and
|
|
30
|
-
nothing else. If the tree is dirty in a way that makes the diff hard to read, say
|
|
31
|
-
so and let the user decide; never tidy it yourself. A review that loses
|
|
32
|
-
uncommitted work is worse than no review.
|
|
33
|
-
|
|
34
|
-
PR mode needs no checkout at all: `gh pr diff` gives the patch, and
|
|
35
|
-
`gh api repos/{owner}/{repo}/contents/{path}?ref={sha}` gives any file at the PR
|
|
36
|
-
head.
|
|
37
|
-
|
|
38
|
-
## Gather
|
|
39
|
-
|
|
40
|
-
PR mode:
|
|
41
|
-
|
|
42
|
-
```bash
|
|
43
|
-
gh pr view <num> --repo tetherto/qvac-harness \
|
|
44
|
-
--json title,body,author,headRefName,headRefOid,baseRefName,files,additions,deletions,state,isDraft,mergeable
|
|
45
|
-
gh pr diff <num> --repo tetherto/qvac-harness --patch > /tmp/pr-<num>.patch
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
Read the patch from the file with Read/Grep rather than re-running `gh` — it is
|
|
49
|
-
the same bytes every time and the file is greppable.
|
|
50
|
-
|
|
51
|
-
Local mode:
|
|
52
|
-
|
|
53
|
-
```bash
|
|
54
|
-
git diff --staged > /tmp/local-staged.patch
|
|
55
|
-
git diff > /tmp/local-unstaged.patch
|
|
56
|
-
git status --porcelain=v1
|
|
57
|
-
git ls-files --others --exclude-standard # untracked, easy to miss
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
For a branch rather than a working tree: `git diff main...HEAD` (three dots —
|
|
61
|
-
the merge base, not the tip).
|
|
62
|
-
|
|
63
|
-
## CI
|
|
64
|
-
|
|
65
|
-
One workflow gates this repo: **Integrate** (`.github/workflows/ci.yml`), a
|
|
66
|
-
single `Lint & Tests` job. `publish.yml` runs on release, not on PRs.
|
|
67
|
-
|
|
68
|
-
Its steps are each a separate way to fail, and the last three catch what a
|
|
69
|
-
local `bun run test` does not:
|
|
70
|
-
|
|
71
|
-
| Step | Command | Fails when |
|
|
72
|
-
| ------------------------ | ---------------------- | --------------------------------------------------------------------------------------------- |
|
|
73
|
-
| Lint | `bun run lint` | prettier, lunte or `tsc --noEmit` |
|
|
74
|
-
| Schema is regenerated | `bun run build:schema` | `spec/` is dirty after codegen — someone hand-edited it, or forgot to commit the regeneration |
|
|
75
|
-
| Tests | `bun run test` | the node, bare and addon lanes |
|
|
76
|
-
| Library surface compiles | `bun run build:lib` | the compiled export surface breaks |
|
|
77
|
-
| Sidecar bundle builds | `bun run build:bundle` | the stowed bundle no longer assembles — a new bare import, or a missing addon external |
|
|
78
|
-
|
|
79
|
-
A PR that touches `schema/` and leaves `spec/` stale is the most common red
|
|
80
|
-
here, and it looks nothing like a test failure.
|
|
81
|
-
|
|
82
|
-
```bash
|
|
83
|
-
gh pr checks <num> --repo tetherto/qvac-harness
|
|
84
|
-
gh run view --repo tetherto/qvac-harness --log-failed --job <id> > /tmp/pr-<num>-<id>.log
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
A red `Integrate` is a blocking finding on its own. Read the failing job's log
|
|
88
|
-
before writing a single line of review — half of what looks like a design
|
|
89
|
-
problem is a lint rule.
|
|
90
|
-
|
|
91
|
-
## What to check, in order
|
|
92
|
-
|
|
93
|
-
Stop at the first tier that produces findings worth the author's time; a review
|
|
94
|
-
that lists twelve nits under a broken contract has buried the real thing.
|
|
95
|
-
|
|
96
|
-
**1. Correctness.** Does it do what the title claims? Trace the changed path
|
|
97
|
-
end to end, including the error path. Look for: a promise not awaited, a
|
|
98
|
-
listener never removed, a resource opened on one path and closed on another, an
|
|
99
|
-
error swallowed into a default.
|
|
100
|
-
|
|
101
|
-
**2. Contract and API.** This is a published package, so an exported signature
|
|
102
|
-
is a promise to a consumer.
|
|
103
|
-
|
|
104
|
-
- Anything added to or changed in the export map, `index.ts`, `types/`, or
|
|
105
|
-
`package.json#exports` — is it intentional, and is it a breaking change?
|
|
106
|
-
- `schema/` or `spec/` changes: is the wire format still compatible, and was the
|
|
107
|
-
baseline regenerated (`bun run build:schema`) rather than hand-edited?
|
|
108
|
-
- Does the change match its own type declarations, and do callers in this repo
|
|
109
|
-
still typecheck?
|
|
110
|
-
|
|
111
|
-
**3. House style.** Run the changed files against **js-house-style** — that
|
|
112
|
-
document, not your own taste. Layering, composition on primitives, module size
|
|
113
|
-
and shape, no defensive programming, comment density.
|
|
114
|
-
|
|
115
|
-
**4. Tests.** A behaviour change with no test is a finding. Name the missing
|
|
116
|
-
case rather than asking for "more tests": the tests live under `test/`, run on
|
|
117
|
-
both the node and bare lanes, and a fix without a regression guard will come
|
|
118
|
-
back.
|
|
119
|
-
|
|
120
|
-
**5. Commit type and title.** Per **pr-create**: is this really a `fix` (a
|
|
121
|
-
defect a consumer of a released version could hit), or is it `chore` on code
|
|
122
|
-
that never shipped? Is the title imperative and specific? Does the branch name
|
|
123
|
-
avoid `codex` / `cursor` / `claude`?
|
|
124
|
-
|
|
125
|
-
**6. Scope.** Does the PR do one thing? A behaviour change mixed with an
|
|
126
|
-
unrelated rename is two PRs — say so, and say which commit to split out.
|
|
127
|
-
|
|
128
|
-
**7. Decision records.** Does the change contradict something in
|
|
129
|
-
`docs/decisions/`? If it does, the record is updated or superseded in the same
|
|
130
|
-
PR, not left to rot. Does it settle something non-obvious with no record at all?
|
|
131
|
-
Say which, and what the record would have to state.
|
|
132
|
-
|
|
133
|
-
### Do not over-engineer the review
|
|
134
|
-
|
|
135
|
-
The most damaging thing a review can do is talk a good PR into a worse one. AI
|
|
136
|
-
review skews defensive: a guard here, an abstraction there, a layer to absorb a
|
|
137
|
-
hypothetical, each one permanent debt bolted to a problem that never happened.
|
|
138
|
-
That runs directly against the house style, which does not program defensively.
|
|
139
|
-
|
|
140
|
-
It compounds. Successive reviews each add a layer against a different
|
|
141
|
-
speculative case, one review's fix undoes another's, and the code ends up in a
|
|
142
|
-
corner nobody chose.
|
|
143
|
-
|
|
144
|
-
- **Only raise what is wrong now**, or has a concrete path to being wrong.
|
|
145
|
-
"Someone could later..." is not a finding.
|
|
146
|
-
- **Never propose a guard, wrapper, fallback or abstraction** whose only job is
|
|
147
|
-
to make a hypothetical safe. Let caller bugs crash; that is the contract.
|
|
148
|
-
- **Prefer the fix that deletes code.** If your suggestion makes the diff
|
|
149
|
-
bigger, be sure it earns it.
|
|
150
|
-
- **Simplification is a valid finding; speculative hardening is not.**
|
|
151
|
-
- When you cannot tell whether something is real, ask instead of requesting a
|
|
152
|
-
change, and be willing to land zero findings.
|
|
153
|
-
|
|
154
|
-
## Write the findings
|
|
155
|
-
|
|
156
|
-
Each finding: the file and line, what breaks, and the concrete scenario that
|
|
157
|
-
breaks it. No finding without a failure mode you can state.
|
|
158
|
-
|
|
159
|
-
Drop anything you cannot defend as changing the code, the reviewer's decision,
|
|
160
|
-
or a consumer's experience. Style opinions the house style does not back are
|
|
161
|
-
noise. Say so plainly when the diff is clean: "no `[P1]` or `[P2]`
|
|
162
|
-
findings" is a complete review.
|
|
163
|
-
|
|
164
|
-
Lead with the findings, ordered by severity.
|
|
165
|
-
|
|
166
|
-
### Severity tags
|
|
167
|
-
|
|
168
|
-
Tag every finding `[P1]`, `[P2]` or `[P3]`. Use the tag, not a word, so two
|
|
169
|
-
reviews of the same repo rank things the same way.
|
|
170
|
-
|
|
171
|
-
- `[P1]` — almost-certain bug, data corruption, security issue, CI breaker, or a
|
|
172
|
-
break of behaviour a consumer relies on. In the overview, and **proposed inline
|
|
173
|
-
by default**.
|
|
174
|
-
- `[P2]` — likely bug, non-obvious caveat, contract or API mismatch, subtle
|
|
175
|
-
behaviour change, missing test on a risky path. In the overview, and **proposed
|
|
176
|
-
inline by default**.
|
|
177
|
-
- `[P3]` — minor: a stale comment or doc, an ergonomic improvement, an optional
|
|
178
|
-
cleanup. In the overview when material, and **not proposed inline** unless the
|
|
179
|
-
user asks for them.
|
|
180
|
-
|
|
181
|
-
**Never silently put a `[P3]` in the inline payload.** A review that posts ten
|
|
182
|
-
nits inline teaches the author to skim the next one.
|
|
183
|
-
|
|
184
|
-
**Severity is what the code does today, not what it might do.** A finding whose
|
|
185
|
-
only support is a scenario nobody has hit is not a `[P2]`: either find the path
|
|
186
|
-
that reaches it, or drop it. Zero findings is a legitimate result.
|
|
187
|
-
|
|
188
|
-
If the user says this is a re-review, say explicitly which earlier concerns are
|
|
189
|
-
resolved and which still stand.
|
|
190
|
-
|
|
191
|
-
## Posting (PR mode only)
|
|
192
|
-
|
|
193
|
-
1. Print every proposed comment in chat first: file, line, severity, body.
|
|
194
|
-
The default set is the `[P1]` and `[P2]` findings; name any `[P3]` you are
|
|
195
|
-
holding back so the user can pull it in.
|
|
196
|
-
2. Ask the user to confirm the exact set. Wait for a clear yes.
|
|
197
|
-
3. Create the review as **PENDING**, with no event:
|
|
198
|
-
|
|
199
|
-
```bash
|
|
200
|
-
gh api repos/tetherto/qvac-harness/pulls/<num>/reviews \
|
|
201
|
-
--method POST --input /tmp/review.json
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
where `review.json` has `commit_id` (the `headRefOid` you fetched) and a
|
|
205
|
-
`comments` array of `{path, line, side, body}`, and **no `event` field**. A body
|
|
206
|
-
with `event` submits the review; leaving it out is what makes it pending.
|
|
207
|
-
|
|
208
|
-
4. Hand the user the link and stop:
|
|
209
|
-
`https://github.com/tetherto/qvac-harness/pull/<num>#pullrequestreview-<id>`
|
|
210
|
-
|
|
211
|
-
If a line is not in the diff, GitHub rejects the comment. Anchor to a line the
|
|
212
|
-
patch actually touches, or raise it in the chat overview instead.
|
|
213
|
-
|
|
214
|
-
## Sibling skills
|
|
215
|
-
|
|
216
|
-
- Writing the PR being reviewed → **pr-create**.
|
|
217
|
-
- The rules tier 3 reviews against → **js-house-style**.
|
package/CLAUDE.md
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
# @qvac/harness
|
|
2
|
-
|
|
3
|
-
The QV.AC inference engine: `generate(context)` over the QVAC SDK, plus the tool
|
|
4
|
-
runtime skills execute in. **Inference in, events out** — it knows nothing about
|
|
5
|
-
the app, hyperdb or sync. It runs as a supervised child process (or a Bare thread
|
|
6
|
-
on mobile) that a host spawns and talks to over hrpc.
|
|
7
|
-
|
|
8
|
-
Runs on both Bare and Node. Anything that only works on one is a bug.
|
|
9
|
-
|
|
10
|
-
## Durable invariants
|
|
11
|
-
|
|
12
|
-
- **The published package spawns; it does not import.** The tarball ships the
|
|
13
|
-
prebuilt bundle and its runtime content, and its export map deliberately points
|
|
14
|
-
at files it omits. That map is not broken — do not "fix" it.
|
|
15
|
-
- **`spec/` is generated** by `bun run build:schema`. Never hand-edit it; CI fails
|
|
16
|
-
when it is dirty after regeneration.
|
|
17
|
-
- **Dependency `overrides` pin the resolutions the engine is validated against.**
|
|
18
|
-
Keep them aligned with the direct specs — npm refuses a mismatch on publish.
|
|
19
|
-
- **The cache is the SDK's.** Do not add caller-side history eviction or
|
|
20
|
-
chars-per-token estimation.
|
|
21
|
-
|
|
22
|
-
## Working here
|
|
23
|
-
|
|
24
|
-
- `bun run lint` (prettier + lunte + tsc) and `bun run test` (node, bare and
|
|
25
|
-
addon lanes) before considering a change done.
|
|
26
|
-
- Tests live in `test/` and run under brittle. A non-trivial change ships tests.
|
|
27
|
-
|
|
28
|
-
## Always
|
|
29
|
-
|
|
30
|
-
- **Comment only what the code cannot say.** Why, not what. One or two lines,
|
|
31
|
-
never more. Most code needs none — do not narrate it.
|
|
32
|
-
- **Commits read as if a human wrote them.** No `Co-Authored-By` trailer and no
|
|
33
|
-
AI or agent attribution, in a commit message or a PR.
|
|
34
|
-
- **Durable decisions are in `docs/decisions/`.** Read `INDEX.md` when touching an
|
|
35
|
-
area it lists, and open a record only on a path or keyword match — they are
|
|
36
|
-
reference, not rules. Add one when a change makes a non-obvious lasting choice.
|
|
37
|
-
- **Branch from `main`, and open the PR against `main`.** The one exception is a
|
|
38
|
-
stacked PR, which branches from the PR below it and targets that branch.
|
|
39
|
-
- **Branch names never contain `codex`, `cursor` or `claude`**, in any case.
|