#3313 · the 4th activation path · 2026-08-10

A comment that invites deleting the only path.

Eight skills in this repo are reachable by exactly one route: a literal Read(...) line in an agent body. Every one of those lines carried a comment explaining why it exists — and the explanation was false in the direction that gets the line deleted.

The claim vs the frontmatter

comment (9 lines, 8 agent files):
  "The `rag-retrieval` skill is slash-only, so it cannot be preloaded."

verified at HEAD, all 8 skills:
  user-invocable:            false   → there is NO slash form
  disable-model-invocation:  true    → the model cannot auto-select it

Both doors are shut. The Read works precisely because it bypasses the Skill tool entirely. So the comment names the one path that does not exist and omits the fact that the line beneath it is the only one that does.

Why this is a trap rather than a typo

A careful editor reads "slash-only", checks the skill, finds user-invocable: false, concludes the comment is stale, and tidies it. Or reads "slash-only" and removes the Read as redundant with a slash command. Either way 8 skills lose their only load path and nothing fails — no linter counts this route, so the loss is invisible.

These lines are not incidental. test-skill-reachability.mjs:245-249 records that #3221 deleted 94 dead preload edges and CONVERTED the 7 load-bearing ones into exactly these Read lines. They are the surviving mechanism, documented by a sentence that argues for their removal.

The 8 skills at stake

rag-retrieval            monitoring-observability   langgraph
llm-integration          multimodal-llm             vite-advanced
product-frameworks       web-research-workflow

Fixed wording

- The `langgraph` skill is slash-only, so it cannot be preloaded. Load it …
+ The `langgraph` skill is `user-invocable: false` AND
+ `disable-model-invocation: true`, so it has no slash form and the model
+ cannot auto-select it. **This `Read` is its only load path — do not remove it.**

The guard, and both controls

Correcting eight comments does not stop a ninth from being written. tests/manifests/test-agent-read-path-truthful.mjs asserts the two things that matter:

assertioncatches
no agent claims "slash-only" about a user-invocable: false skillthe wording returning
every Read() target resolves to a real skilla rename missing these string literals — nothing else resolves them
$ node tests/manifests/test-agent-read-path-truthful.mjs
  PASS 9 agent Read() line(s) found (the 4th activation path is present)
  PASS every Read() target resolves to an existing skill
  PASS no agent claims "slash-only" about a non-user-invocable skill

control 1 — reintroduce the false wording:
  FAIL claims "slash-only" about `langgraph`, which is user-invocable: false
control 2 — rename a Read() target:
  FAIL Read() targets a skill that does not exist: langgraph-renamed
restore verified, zero residue

The first assertion also fails if the count of Read lines ever hits zero — a guard that passes an empty repo is the failure mode this milestone exists to remove.

Discovery, verified rather than assumed

$ bash scripts/ci/run-tests.sh tests/manifests
  [RUN]  test-agent-read-path-truthful.mjs
  [PASS] test-agent-read-path-truthful.mjs
  Total tests: 11 · Passed: 11 · Failed: 0

A new test file in this repo has to join three rosters or it silently never runs. Both run-all-tests.sh:297 and ci.yml:633 delegate to scripts/ci/run-tests.sh, whose glob covers test-*.sh AND test-*.mjs (:57) — a .mjs-blind glob had already silently skipped test-skill-activation-channels.mjs once. Confirmed by running the roster, not by reading it.

Where this sits in #3313. The issue reports "29 of 105 skills unreachable". Scoped against the real linters, genuinely broken is 1; 8 are these — reachable in practice, invisible to every gate; 20 are inert reference libraries nothing depends on. This PR fixes neither the 1 nor the 20. It removes the booby trap first, because it is the cheapest change with the worst failure mode: leave it and a future cleanup silently deletes eight working paths, after which the "unreachable" count becomes accurate for the wrong reason.