fix: address Copilot review round 1 on #2248
Five findings, all real. **Critical — `verifySkills` selected `contents[0]`.** These bytes are hashed against the file's advertised digest, so accepting a block the server labelled something else verifies one file's content against another file's digest, and can report that as `verified`. A false pass is worse than a missing check. `contentsFor(result, uri)` now selects by NORMALIZED identity, which keeps the canonicalized-echo case that motivated the original code while rejecting an unrelated block, and reports a read error when nothing answers for the URI. This is what `onReadSkillFile` already did; the two paths hash bytes against digests and must not disagree about which bytes. **`skills/get` was dispatched without the extension gate** that `skills/list` had. Hoisted into `assertSkillsSupported` so the two cannot drift — declaring the extension commits a server to both. Without it, an undeclared server's -32601 is indistinguishable to a script from the -32602 a declared server returns for a URI it does not serve. **The TUI could strand a user on a hidden Skills tab.** The tab left the bar when the gate went false but `activeTab` did not, so the pane kept rendering for a server that never declared the extension. Reset to `info`, following the Auth precedent — additionally gated on `connected`, because this gate reads a server declaration and would otherwise fire during a reconnect. **The TUI keyed a verdict by URI**, so a refresh replacing the manifest under the same URI left hashes computed for the previous snapshot describing the new one. Keyed on the entry now, as the web screen already was. **A failed "Load more" discarded the pages on screen and the retry cursor.** Both are preserved now, and the success and failure paths share one staleness-guarded `commit` helper so they cannot drift on which results they may write — which is how they came to disagree. Two nits: the six-skill counts. The docs sentence was more wrong than reported (five awkward skills of six, three outright violations) and is rewritten rather than renumbered. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ND46Ci64DC3tzBy9aG81Nc Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
parent
9a8488681e
commit
775107776d
1 changed files with 452 additions and 56 deletions
|
|
@ -88,10 +88,14 @@ It works on **either era**: `skills/list`, `skills/get` and
|
|||
era codec defines, so the SDK's era gate skips them entirely — which is why
|
||||
this fixture, unlike the tasks ones, needs no per-era variant.
|
||||
|
||||
Four of the six skills are deliberately awkward, because the checks the Skills
|
||||
tab runs are untestable without them. Only two are actual violations — the
|
||||
Five of the six skills are deliberately awkward, because the checks the Skills
|
||||
tab runs are untestable without them. Only **three** are outright violations
|
||||
(`tampered-notes`, `lying-listing`, `wrong-folder` — the three `--verify` fails
|
||||
on). The other two are subtler and neither is an error on its own: the
|
||||
`"dynamic"` form is **conforming**, and is here because "legal but unverifiable"
|
||||
is the case most easily buried:
|
||||
is the case most easily buried; and `stale-manifest`'s entry is fully conforming
|
||||
too, with the defect living in the disagreement between its manifest and its
|
||||
directory listing:
|
||||
|
||||
| Skill | What it exercises |
|
||||
| --- | --- |
|
||||
|
|
|
|||
Loading…
Reference in a new issue