Skip to content

fix(framework): a Copilot skill call opens no step, so its session journals as unattributed #701

Closed

Description

@blafourcade

On the payload shape a real Copilot session actually sends, the journal records the session and never a step. Every record in it reads unattributed, which is the honest answer and not a useful one.

What is known

lib/step-starts.js reads Copilot's skill invocation as:

copilot: skillNameFromArgument({
  toolField: "toolName", toolName: "skill",
  argumentsField: "toolArgs", nameField: "skill",
})

That is the canonical builder's spelling. The _vsCodeCompat builder — confirmed against @github/copilot@1.0.80 in #681 — sends Claude Code's spelling instead:

{ "hook_event_name": "PostToolUse", "session_id": "…", "timestamp": "…", "cwd": "…",
  "tool_name": "Bash", "tool_input": { "command": "ls -a ." }, "tool_result": "…" }

toolName is absent, so the reader returns null on every tool call and no step_start line is ever written.

What is not known, and must be measured first

The capture in #681 used a Bash tool. It establishes the field names for a tool call, and nothing about a skill call:

  • What the compat builder puts in tool_name when a skill is invoked. Claude Code sends Skill; the canonical Copilot builder sends skill. Neither can be assumed for the third.
  • Where the skill's name sits inside tool_input. The canonical builder uses a skill key inside toolArgs; whether the compat builder matches Claude Code's tool_input.skill is unverified.

Two field values, both guessable and neither known. Guessing them is exactly the mistake #681 was opened to correct, and it would fail the same way — silently, with a journal that looks healthy.

Done when

  • A real Copilot session that invokes a skill is captured, and its PostToolUse payload held as a fixture.
  • The step reader recognises whichever spelling that payload carries, alongside the canonical one, and a test fails if either stops being recognised.
  • A Copilot session running a skill produces a step_start line naming it, and its records attribute to that step rather than reading unattributed.

Bounds

Copilot is outside the current milestone's tool coverage (epic #631 excludes the four remaining tools), so this does not block it. It matters for the milestone after, where per-step attribution is claimed on more than one tool.

Where it was found

While capturing the payload for #681. detectHost is fixed there; this is the next thing that reads the same payload and does not understand it.

Activity

  1. blafourcade commented on Aug 22, 2026

    @blafourcade
    ContributorAuthor

    Captured, and neither value was derivable

    One real @github/copilot@1.0.80 session, asked to invoke a skill by name. The PostToolUse payload, key set unmodified:

    {
      "hook_event_name": "PostToolUse", "session_id": "…", "timestamp": "…", "cwd": "…",
      "tool_name": "skill", "tool_input": { "skill": "00-init" }, "tool_result": { … }
    }

    The two unknowns this ticket refused to guess:

    • tool_name is "skill" — the canonical Copilot builder's lowercase spelling, not Claude Code's "Skill".
    • The name sits at tool_input.skill, and tool_input arrives as an object — Claude Code's field name, but not the canonical Copilot builder's JSON-string toolArgs.

    So the compat builder mixes one host's tool-name spelling with another host's argument shape. Neither value follows from the other two captures, and picking either convention wholesale would have got one of the two wrong — silently, with a journal that looks healthy. That is exactly the failure #681 was opened to correct, and the reason this ticket said capture first.

    What changed

    step-starts.js gained a small combinator that runs several argument-family readers in sequence and takes the first name found. Copilot's entry now runs both the canonical (toolName / toolArgs) and the compat (tool_name / tool_input) readers through it. Both shapes are recognised; neither replaced the other, because both are real captures.

    A tool call that is not a skill still opens nothing, on either shape — both readers gate on the tool name.

    New fixture copilot-compat-post-tool-use-skill.json, redacted the way its neighbours are. Two tests: a compat skill call leaves a step_start naming 00-init, and a compat Bash call opens none. The fixtures README's sentence saying the compat shape "never opens a step line" was itself written by #681 and is now false; corrected.

    What this does and does not buy

    A Copilot session's records now attribute to the step that was running, at journal-interval strength, instead of reading unattributed. That is attribution of which step ran.

    It is not a figure of what it cost. Copilot's own files carry outputTokens once at shutdown for the whole session and no per-request counter, so no amount can be placed inside a step however well the boundary is known. Closing that needs its opt-in OTLP export or a per-request field nobody has ever observed on disk — #697 and #653, not this.

    Gate: 324 plugin specs pass, 0 broken links. One of three budgeted sessions used.

  2. moved this from Ideation to In review in AIDD Roadmapon Aug 22, 2026
  3. blafourcade commented on Aug 22, 2026

    @blafourcade
    ContributorAuthor

    Done and awaiting review in #706, which closes this on merge.

    The work is on claude/aidd-telemetry-layer-e403uf, eleven commits, targeting next. Gate at the time of push: 365 plugin specs, 1,931 CLI unit, 577 integration, 178 e2e, tsc and biome clean, no broken markdown links.

    Read the eleven commits rather than the pull request's file count — the branch carries its own copy of the CLI migration that next has since received, so the diff counts it twice. The range and the real figures are in the first comment on #706: 142 files, +10,518 −418.

    Every claim about a tool in this work rests on a session that was actually run. The negative results are kept in full in aidd_docs/tasks/2026_08/2026_08_22_telemetry-every-tool/measurements.md, including the two probes that disagreed about OpenCode and the measurement that reconciled them.

  4. added a commit that references this issue on Aug 28, 2026
  5. blafourcade commented on Sep 2, 2026

    @blafourcade
    ContributorAuthor

    Delivered by #706, squash-merged into next as 627408f.

  6. moved this from In review to Done in AIDD Roadmapon Sep 2, 2026
  7. added theissue type on Sep 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Fields

    Priority

    Medium

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions