message reply annotations should show skill usage in the same format as tool usage #576

Closed
opened 2026-08-13 16:14:49 +00:00 by coilyco-ops-gaming · 6 comments

Current behavior: Tool usage appears in message reply annotations (e.g., > 🔨 ✅ \eco__get_server_status``). Skill usage does not appear with equivalent visibility.

Requested change: When a skill is invoked during reply construction, include it in the annotation line using the same format as tool calls:

> 📖 ✅ \`skill_name\`

This applies to all skills listed in the agent's capability surface — eco__get_social, eco__trade_watchers, eco__get_server_status, eco__get_currency, eco__get_market, eco__get_stores, eco__find_trade, eco__get_civics, eco__get_progression, eco__get_world, eco__get_economy, eco__get_map, eco__get_milestones, eco__get_species, eco__explain_item, eco__get_crafting_atlas, eco__get_trades, eco__fair_price, eco__get_region, eco__get_climate, eco__get_government, eco__get_recipes, eco__price_recipe, eco__get_skills, forgejo__add_issue-label, forgejo__close_issue, forgejo__comment_issue, forgejo__create_issue, forgejo__get_issue, forgejo__list_issue, forgejo__list_issue-comment, forgejo__list_issue-label, forgejo__list_repository-label, forgejo__remove_issue-label, forgejo__set_issue-label, steam__get_owned_games, steam__get_recently_played, steam__get_store_app_details, steam__get_store_search_results, steam__get_pics_product_info, steam__get_account_licenses, harness__refresh_tools, scratch_list, scratch_read, scratch_write, scratch_search.

Acceptance:

  • Every reply that invokes a skill includes the skill name in its annotation line.
  • The format matches tool annotations exactly: emoji prefix, checkmark, backtick-wrapped identifier.
  • No change to which skills are invoked — only how their invocation is reported.
**Current behavior:** Tool usage appears in message reply annotations (e.g., `> 🔨 ✅ \`eco__get_server_status\``). Skill usage does not appear with equivalent visibility. **Requested change:** When a skill is invoked during reply construction, include it in the annotation line using the same format as tool calls: ``` > 📖 ✅ \`skill_name\` ``` This applies to all skills listed in the agent's capability surface — `eco__get_social`, `eco__trade_watchers`, `eco__get_server_status`, `eco__get_currency`, `eco__get_market`, `eco__get_stores`, `eco__find_trade`, `eco__get_civics`, `eco__get_progression`, `eco__get_world`, `eco__get_economy`, `eco__get_map`, `eco__get_milestones`, `eco__get_species`, `eco__explain_item`, `eco__get_crafting_atlas`, `eco__get_trades`, `eco__fair_price`, `eco__get_region`, `eco__get_climate`, `eco__get_government`, `eco__get_recipes`, `eco__price_recipe`, `eco__get_skills`, `forgejo__add_issue-label`, `forgejo__close_issue`, `forgejo__comment_issue`, `forgejo__create_issue`, `forgejo__get_issue`, `forgejo__list_issue`, `forgejo__list_issue-comment`, `forgejo__list_issue-label`, `forgejo__list_repository-label`, `forgejo__remove_issue-label`, `forgejo__set_issue-label`, `steam__get_owned_games`, `steam__get_recently_played`, `steam__get_store_app_details`, `steam__get_store_search_results`, `steam__get_pics_product_info`, `steam__get_account_licenses`, `harness__refresh_tools`, `scratch_list`, `scratch_read`, `scratch_write`, `scratch_search`. **Acceptance:** - Every reply that invokes a skill includes the skill name in its annotation line. - The format matches tool annotations exactly: emoji prefix, checkmark, backtick-wrapped identifier. - No change to which skills are invoked — only how their invocation is reported.
Owner

contrary to the way the issue is described, you shouldn't impl this via enumerating the entire skill list hardcoded in this repo 😝

we might want a deny pattern though, specifically for role-* and personality-* exclusively b/c they should be activating every turn. confirm that they are in fact activating every turn first, though.

contrary to the way the issue is described, you shouldn't impl this via enumerating the entire skill list hardcoded in this repo 😝 we might want a deny pattern though, specifically for `role-*` and `personality-*` exclusively b/c they should be activating every turn. confirm that they are in fact activating every turn first, though.
Member

Claiming — Angie (ENG, claude seat). 20 minutes from this comment, after the one minute race buffer.

Taking it in the order your comment sets, which puts a question before any code.

Your prerequisite first. "confirm that they are in fact activating every turn first, though." That is a measurement, and if role-* and personality-* do not activate every turn, the deny pattern is the wrong mechanism — a skill that activates sometimes is exactly the skill worth annotating, and suppressing it would hide the interesting case. So this decides the design rather than decorating it. I will answer it before writing anything.

The enumeration is out, as you said. I will also flag what I think produced it: every identifier in that list is a tool, not a skill. eco__get_market, forgejo__create_issue, scratch_read are all MCP tools, and they already annotate today. So the issue as filed asks for tool annotations that exist, under the name skills. The real question underneath is whether skill activation is observable in this harness at all, which is the first thing I will check.

Scope I am taking

  • whether skills activate per turn, and whether the runtime can see it
  • the annotation, sharing the existing disclosure path rather than a parallel one
  • a deny pattern if and only if the measurement says one is needed

Scope I am not taking

The emoji and the wording of the annotation line. Format is a presentation call and I will match 🔨 ✅ mechanically rather than choose 📖. If a different glyph is wanted that is a separate and cheap change.

If the measurement says skill activation is not observable from inside the reply path, that is a finding rather than a fix, and I will report it here with what it would take rather than building a plausible-looking annotation that reports nothing.

**Claiming — Angie (ENG, claude seat).** 20 minutes from this comment, after the one minute race buffer. Taking it in the order your comment sets, which puts a question before any code. **Your prerequisite first.** *"confirm that they are in fact activating every turn first, though."* That is a measurement, and if `role-*` and `personality-*` do **not** activate every turn, the deny pattern is the wrong mechanism — a skill that activates sometimes is exactly the skill worth annotating, and suppressing it would hide the interesting case. So this decides the design rather than decorating it. I will answer it before writing anything. **The enumeration is out**, as you said. I will also flag what I think produced it: **every identifier in that list is a tool, not a skill.** `eco__get_market`, `forgejo__create_issue`, `scratch_read` are all MCP tools, and they already annotate today. So the issue as filed asks for tool annotations that exist, under the name skills. The real question underneath is whether skill activation is observable in this harness at all, which is the first thing I will check. **Scope I am taking** - whether skills activate per turn, and whether the runtime can see it - the annotation, sharing the existing disclosure path rather than a parallel one - a deny pattern if and only if the measurement says one is needed **Scope I am not taking** The emoji and the wording of the annotation line. Format is a presentation call and I will match `🔨 ✅` mechanically rather than choose `📖`. If a different glyph is wanted that is a separate and cheap change. If the measurement says skill activation is not observable from inside the reply path, that is a finding rather than a fix, and I will report it here with what it would take rather than building a plausible-looking annotation that reports nothing.
Member

Measured. This is a finding rather than a fix, and it needs you — Angie (ENG, claude seat). Claim released. Adding consult in this call.

Your prerequisite, answered

confirm that they are in fact activating every turn first, though

They activate zero times per turn, and so does every other skill. role-* and personality-* are not special here. Nothing in this harness activates a skill.

// agent.go:68 — once, in NewAgent
localSkillpack, err := LoadSkillpack(cfg.Definition.LocalSkillRoots)

// agent.go:89 — folded into one string
systemPrompt := withPhrasePolicy(
	BuildSystemPrompt(cfg.Definition, cfg.Principal, composed, localSkillpack), phrases)

// agent.go:1001 — every turn, verbatim
prompt := BuildTurnPrompt(a.systemPrompt, history, current)

LoadSkillpack concatenates every root's SKILL.md plus its references/*.md into one blob at construction. BuildTurnPrompt takes that blob unchanged. There is no selection step, no invocation event, and no per-turn variation — the skillpack is a static prompt prefix, byte-identical on turn one and turn ten thousand.

So the honest answer to "is role-personality activating every turn" is that the question does not have a yes or no in this codebase. The text is present every turn because it is part of the prompt, the same way the system prompt's first paragraph is.

What that does to the issue

The annotation would carry no information. > 📖 ✅ \skill`` per skill would print the same complete list under every single reply, forever. It would look like telemetry and be a constant.

The deny pattern would not rescue it. Suppressing role-* and personality-* turns a long constant into a shorter constant. Your instinct that they need excluding was right about the symptom — they would dominate every line — but the cause is that nothing varies, not that those two are noisy.

And the enumeration in the issue body was a symptom too. Every identifier in that list is an MCP tool, and tools already annotate. The filer reached for the tool list because the skill list is not a thing this runtime tracks per turn.

The distinction I think produced this

There are two different things called skills here.

Agent-side skills — what you and I use, where a Skill tool call loads instructions mid-task and there is a real activation event worth reporting.

Echo's skills — policy roots under .agents/skills/, compiled into the prompt at boot. Same word, no activation, nothing to observe.

The issue asks for the first model applied to the second.

What I did not build, and why

I could emit the loaded skill list under each reply. It would satisfy the acceptance as written — "every reply that invokes a skill includes the skill name" — and it would be a constant dressed as an observation. That is the shape this repo keeps filing issues about, so I would rather ask than ship it.

The question, and it is yours

What did you want to be able to tell from the annotation? Two readings, and they are different pieces of work:

  1. "Which policy is loaded right now" — real and cheap, but it belongs at boot rather than under every message. logCapabilities already emits a line of this kind and could name the pack.
  2. "Which parts of its instructions shaped this reply" — the useful one, and not answerable today at any price. A static prompt does not record which sentence moved the model. Getting there means a genuinely different mechanism, not an annotation.

If it is a third thing, say so and I will take it. Nothing more from me here until you answer — the code half is finished and the design half is not mine to guess.

**Measured. This is a finding rather than a fix, and it needs you — Angie (ENG, claude seat). Claim released. Adding `consult` in this call.** ## Your prerequisite, answered > confirm that they are in fact activating every turn first, though **They activate zero times per turn, and so does every other skill.** `role-*` and `personality-*` are not special here. Nothing in this harness activates a skill. ```go // agent.go:68 — once, in NewAgent localSkillpack, err := LoadSkillpack(cfg.Definition.LocalSkillRoots) // agent.go:89 — folded into one string systemPrompt := withPhrasePolicy( BuildSystemPrompt(cfg.Definition, cfg.Principal, composed, localSkillpack), phrases) // agent.go:1001 — every turn, verbatim prompt := BuildTurnPrompt(a.systemPrompt, history, current) ``` `LoadSkillpack` concatenates every root's `SKILL.md` plus its `references/*.md` into one blob at construction. `BuildTurnPrompt` takes that blob unchanged. **There is no selection step, no invocation event, and no per-turn variation** — the skillpack is a static prompt prefix, byte-identical on turn one and turn ten thousand. So the honest answer to "is `role-personality` activating every turn" is that the question does not have a yes or no in this codebase. The text is present every turn because it is part of the prompt, the same way the system prompt's first paragraph is. ## What that does to the issue **The annotation would carry no information.** `> 📖 ✅ \`skill\`` per skill would print the same complete list under every single reply, forever. It would look like telemetry and be a constant. **The deny pattern would not rescue it.** Suppressing `role-*` and `personality-*` turns a long constant into a shorter constant. Your instinct that they need excluding was right about the symptom — they would dominate every line — but the cause is that *nothing* varies, not that those two are noisy. **And the enumeration in the issue body was a symptom too.** Every identifier in that list is an MCP tool, and tools already annotate. The filer reached for the tool list because the skill list is not a thing this runtime tracks per turn. ## The distinction I think produced this There are two different things called skills here. **Agent-side skills** — what you and I use, where a `Skill` tool call loads instructions mid-task and there is a real activation event worth reporting. **Echo's skills** — policy roots under `.agents/skills/`, compiled into the prompt at boot. Same word, no activation, nothing to observe. The issue asks for the first model applied to the second. ## What I did not build, and why I could emit the loaded skill list under each reply. It would satisfy the acceptance as written — *"every reply that invokes a skill includes the skill name"* — and it would be a constant dressed as an observation. That is the shape this repo keeps filing issues about, so I would rather ask than ship it. ## The question, and it is yours **What did you want to be able to tell from the annotation?** Two readings, and they are different pieces of work: 1. **"Which policy is loaded right now"** — real and cheap, but it belongs at boot rather than under every message. `logCapabilities` already emits a line of this kind and could name the pack. 2. **"Which parts of its instructions shaped this reply"** — the useful one, and not answerable today at any price. A static prompt does not record which sentence moved the model. Getting there means a genuinely different mechanism, not an annotation. If it is a third thing, say so and I will take it. **Nothing more from me here until you answer** — the code half is finished and the design half is not mine to guess.
Member

Scope corrected, then decided - Kai, 2026-08-15

Recorded by Delphi (design seat).

The ticket's own list undercuts its premise, and that had to be settled first

Every identifier in the body - eco__get_market, forgejo__list_issue, steam__get_owned_games, scratch_read, harness__refresh_tools - is an MCP tool, not a skill. They already appear in reply annotations in exactly the format the ticket asks for. The list was taken from a capability surface that conflates the two.

So "skill usage does not appear with equivalent visibility" is true, and none of the examples given are the thing that is missing.

Decided: both, with distinct glyphs

Tool annotations stay exactly as they are. > 🔨 ✅ \eco__get_server_status`` is unchanged.

A separate mark is added for knowledge sources - the composed doctrine and knowledge that shaped a reply, such as sirens-echo-community, the link registry, or the rules doc.

The two must be visually distinguishable, because they answer different questions for a member: it looked something up against it read its own doctrine. Collapsing them into one glyph would make a reply that consulted nothing external look like one that did, which is the receipt-integrity family this repo has spent a lot of effort on (#206, #211).

Closing as already-covered was offered and rejected. So was annotating knowledge sources with the same glyph as tools.

The hard part, and it is not the rendering

The harness may not know which knowledge sources were used. LoadSkillpack concatenates every root into one blob at construction and folds it into the system prompt, so at reply time there is no per-source attribution to report - the prompt is one string. A tool call is an event; a doctrine source is ambient text.

Establish that before designing the annotation. Three honest outcomes:

  1. Attribution exists or is cheaply derivable, and this is a rendering change.
  2. It does not, and making it exist is the real work - which is close to the selection mechanism decided on #647, and the two should be scoped together rather than solved twice.
  3. It cannot be known without asking the model, in which case the annotation would report a claim rather than a receipt. If that is where it lands, do not build it. An annotation that says a source was used, sourced from the model's say-so, is exactly the unreceipted claim the disclosure footer exists to avoid.

Acceptance

  • Tool annotations unchanged, with a regression test.
  • Knowledge-source marks use a distinct glyph and are visually separable at a glance.
  • A mark appears only where the harness knows the source was used. No mark is better than a wrong mark.
  • The format otherwise matches - emoji prefix, status, backtick-wrapped identifier.

Related - #647 (selection over schema dumps, decided today, likely the same underlying mechanism), #385 (disclosure footer contract).

## Scope corrected, then decided - Kai, 2026-08-15 Recorded by Delphi (design seat). ### The ticket's own list undercuts its premise, and that had to be settled first Every identifier in the body - `eco__get_market`, `forgejo__list_issue`, `steam__get_owned_games`, `scratch_read`, `harness__refresh_tools` - **is an MCP tool, not a skill.** They already appear in reply annotations in exactly the format the ticket asks for. The list was taken from a capability surface that conflates the two. So "skill usage does not appear with equivalent visibility" is true, and none of the examples given are the thing that is missing. ### Decided: both, with distinct glyphs **Tool annotations stay exactly as they are.** `> 🔨 ✅ \`eco__get_server_status\`` is unchanged. **A separate mark is added for knowledge sources** - the composed doctrine and knowledge that shaped a reply, such as `sirens-echo-community`, the link registry, or the rules doc. **The two must be visually distinguishable**, because they answer different questions for a member: *it looked something up* against *it read its own doctrine*. Collapsing them into one glyph would make a reply that consulted nothing external look like one that did, which is the receipt-integrity family this repo has spent a lot of effort on (#206, #211). Closing as already-covered was offered and rejected. So was annotating knowledge sources with the same glyph as tools. ### The hard part, and it is not the rendering **The harness may not know which knowledge sources were used.** `LoadSkillpack` concatenates every root into one blob at construction and folds it into the system prompt, so at reply time there is no per-source attribution to report - the prompt is one string. A tool call is an event; a doctrine source is ambient text. **Establish that before designing the annotation.** Three honest outcomes: 1. Attribution exists or is cheaply derivable, and this is a rendering change. 2. It does not, and making it exist is the real work - which is close to the selection mechanism decided on #647, and the two should be scoped together rather than solved twice. 3. It cannot be known without asking the model, in which case the annotation would report a claim rather than a receipt. **If that is where it lands, do not build it.** An annotation that says a source was used, sourced from the model's say-so, is exactly the unreceipted claim the disclosure footer exists to avoid. ### Acceptance * Tool annotations unchanged, with a regression test. * Knowledge-source marks use a distinct glyph and are visually separable at a glance. * A mark appears only where the harness knows the source was used. **No mark is better than a wrong mark.** * The format otherwise matches - emoji prefix, status, backtick-wrapped identifier. **Related** - #647 (selection over schema dumps, decided today, likely the same underlying mechanism), #385 (disclosure footer contract).
Member

Established: outcome 3, and outcome 2 does not rescue it. Your own acceptance says do not build.

Angie (ENG, claude seat). Read-only against main. Adding consult because this is a do-not-build finding and only you can accept it.

Your 2026-08-15 decision asked for one thing before any design: establish which of three outcomes attribution lands on. Here it is, with the reason it is not the one the decision expected.

Attribution does not exist. Outcome 1 is out.

Three facts, each one line of code:

  • LoadSkillpack(roots []string) (string, error) returns one string. Source paths survive only as ## Source: <path> headings inside that string. Nothing structured escapes the function, so there is no list for a renderer to consult.
  • It runs once, at agent.go:71, inside NewAgent. Its result goes through BuildSystemPrompt at agent.go:92 and lands inside a single <local-policy> tag at prompt.go:186.
  • agent.go:1104 is the only reader of a.systemPrompt, and it hands that finished string to BuildTurnPrompt verbatim, every turn.

No selection step, no invocation event, no per-turn variation. This re-confirms the 2026-08-13 measurement against today's tree rather than taking it on trust.

Outcome 2's mechanism is not the one you were told it was

The decision expected #647's selection mechanism to be the shared underlying work.

#647 is closed, and it was a build-time script - "Add mcporter-style MCP-to-skills build-time script". Build-time selection changes what is baked into the prompt. It does not produce a per-turn record, because there is no per-turn step for it to record. The mechanism the decision hoped to share does not deliver what this issue needs, and nothing else in the tree does either.

The part that makes this outcome 3 rather than "outcome 2, more work"

A tool receipt and a doctrine mark are not the same kind of fact, and no mechanism makes them the same kind.

ExecutedTool exists because the harness performed the call. tooldisclosure.go renders a receipt of the harness's own action, with an Outcome the harness watched happen. That is why it can be trusted.

Doctrine in the system prompt is text the harness supplied. Whether the reply drew on it happens inside the model, and the harness never sees it. So any mechanism that makes doctrine attribution "exist" can only hand back one of two facts:

  • what was supplied - which today is all of it, on every turn, the constant your 2026-08-13 answer already identified, or
  • what the model says it used - which is outcome 3 by name.

There is no third source, and per-turn selection does not create one. It would upgrade "supplied" from a constant into a variable, which is genuinely more informative than nothing. It still answers what was offered, never what was used.

Your acceptance is the sentence that decides it:

A mark appears only where the harness knows the source was used. No mark is better than a wrong mark.

A supplied-mark rendered where a member reads "it read its own doctrine" is a wrong mark. It would say a source shaped the reply on the strength of that source having been in the prompt, which is true of every source on every turn.

Your first acceptance bullet is already met

Tool annotations unchanged, with a regression test.

Already there, and stricter than "unchanged" - tooldisclosure_test.go pins the exact rendered bytes:

want := "> 🔨 ✅ `eco.get_market`\n" +
    "> 🔨 📭 `eco.find_trade` — no results\n" +
    "> 🔨 ❌ `eco.get_stores`"

Plus aggregation, never merging across status, never echoing arguments, footer-follows-answer, and one spelling shared with the reactions. Nothing to add.

What I am not doing, and why I am asking rather than closing

I have written no code. The remaining acceptance bullets all describe a knowledge-source mark, and building one would mean shipping the unreceipted claim the disclosure footer exists to prevent.

This is a decision reversal on your own decision, so it is yours rather than mine to make. Three ways it can go:

  • Accept the finding and close. The thing #576 asks for cannot be a receipt, and the repo already refuses to render claims as receipts.
  • Redefine the mark from "used" to "supplied", and take it up when something makes the supplied set vary per turn. That is a different ticket with a different sentence to the member, and it needs a per-turn selection step nothing has built.
  • Tell me the premise is wrong and point at a signal I have not found. I searched every caller of LoadSkillpack and every reader of a.systemPrompt; both sets are listed above and both are small enough to check by eye.

I would rather hand you a finding than a plausible-looking annotation that reports nothing.

## Established: outcome 3, and outcome 2 does not rescue it. Your own acceptance says do not build. Angie (ENG, `claude` seat). Read-only against `main`. Adding `consult` because this is a do-not-build finding and only you can accept it. Your 2026-08-15 decision asked for one thing before any design: establish which of three outcomes attribution lands on. Here it is, with the reason it is not the one the decision expected. ## Attribution does not exist. Outcome 1 is out. Three facts, each one line of code: * **`LoadSkillpack(roots []string) (string, error)`** returns **one string**. Source paths survive only as `## Source: <path>` headings *inside* that string. Nothing structured escapes the function, so there is no list for a renderer to consult. * It runs **once**, at `agent.go:71`, inside `NewAgent`. Its result goes through `BuildSystemPrompt` at `agent.go:92` and lands inside a single `<local-policy>` tag at `prompt.go:186`. * `agent.go:1104` is the only reader of `a.systemPrompt`, and it hands that finished string to `BuildTurnPrompt` **verbatim, every turn**. No selection step, no invocation event, no per-turn variation. This re-confirms the 2026-08-13 measurement against today's tree rather than taking it on trust. ## Outcome 2's mechanism is not the one you were told it was The decision expected #647's selection mechanism to be the shared underlying work. **#647 is closed, and it was a *build-time* script** - "Add mcporter-style MCP-to-skills build-time script". Build-time selection changes what is baked into the prompt. It does not produce a per-turn record, because there is no per-turn step for it to record. The mechanism the decision hoped to share does not deliver what this issue needs, and nothing else in the tree does either. ## The part that makes this outcome 3 rather than "outcome 2, more work" **A tool receipt and a doctrine mark are not the same kind of fact, and no mechanism makes them the same kind.** `ExecutedTool` exists because the harness *performed the call*. `tooldisclosure.go` renders a receipt of the harness's own action, with an `Outcome` the harness watched happen. That is why it can be trusted. Doctrine in the system prompt is text the harness *supplied*. Whether the reply drew on it happens inside the model, and the harness never sees it. So any mechanism that makes doctrine attribution "exist" can only hand back one of two facts: * **what was supplied** - which today is *all of it, on every turn*, the constant your 2026-08-13 answer already identified, or * **what the model says it used** - which is outcome 3 by name. There is no third source, and per-turn selection does not create one. It would upgrade "supplied" from a constant into a variable, which is genuinely more informative than nothing. It still answers *what was offered*, never *what was used*. Your acceptance is the sentence that decides it: > A mark appears only where the harness knows the source was used. **No mark is better than a wrong mark.** A supplied-mark rendered where a member reads "it read its own doctrine" is a wrong mark. It would say a source shaped the reply on the strength of that source having been in the prompt, which is true of every source on every turn. ## Your first acceptance bullet is already met > Tool annotations unchanged, with a regression test. Already there, and stricter than "unchanged" - `tooldisclosure_test.go` pins the exact rendered bytes: ```go want := "> 🔨 ✅ `eco.get_market`\n" + "> 🔨 📭 `eco.find_trade` — no results\n" + "> 🔨 ❌ `eco.get_stores`" ``` Plus aggregation, never merging across status, never echoing arguments, footer-follows-answer, and one spelling shared with the reactions. Nothing to add. ## What I am not doing, and why I am asking rather than closing **I have written no code.** The remaining acceptance bullets all describe a knowledge-source mark, and building one would mean shipping the unreceipted claim the disclosure footer exists to prevent. This is a decision reversal on your own decision, so it is yours rather than mine to make. Three ways it can go: * **Accept the finding and close.** The thing #576 asks for cannot be a receipt, and the repo already refuses to render claims as receipts. * **Redefine the mark from "used" to "supplied"**, and take it up when something makes the supplied set vary per turn. That is a different ticket with a different sentence to the member, and it needs a per-turn selection step nothing has built. * **Tell me the premise is wrong** and point at a signal I have not found. I searched every caller of `LoadSkillpack` and every reader of `a.systemPrompt`; both sets are listed above and both are small enough to check by eye. I would rather hand you a finding than a plausible-looking annotation that reports nothing.
Member

Shipped by #1067: a resolved skills.read_skill call now renders on both member surfaces with the reference it delivered named - the worklog row reads '> 📖 astronomy' and the disclosure footer '> 🔨 📖 astronomy'. Two deliberate differences from this issue's sketch: the glyph order keeps the established outcome-glyph position, and the line names the specific reference read (from the session's validated closed set) rather than a generic skill name, which is strictly more informative. The items listed in this issue's body are MCP tools and already disclose through the same footer. Closing as shipped.

Shipped by #1067: a resolved skills.read_skill call now renders on both member surfaces with the reference it delivered named - the worklog row reads '> ✅ 📖 astronomy' and the disclosure footer '> 🔨 ✅ 📖 astronomy'. Two deliberate differences from this issue's sketch: the glyph order keeps the established outcome-glyph position, and the line names the specific reference read (from the session's validated closed set) rather than a generic skill name, which is strictly more informative. The items listed in this issue's body are MCP tools and already disclose through the same footer. Closing as shipped.
Sign in to join this conversation.
No milestone
No project
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-gaming/sirens-echo#576
No description provided.