CopilotAtelier.psd1
|
@{ RootModule = 'CopilotAtelier.psm1' # Replaced at build time by GitVersion. ModuleVersion = '4.0.0' GUID = '67bbef0b-f4de-4c1b-bb5a-b34104beb5b7' Author = 'raandree' CompanyName = 'raandree' Copyright = '(c) raandree. All rights reserved.' Description = 'Portable GitHub Copilot customization library. Ships custom agents, auto-applied instructions, on-demand skills, prompt templates, and lifecycle hooks, and installs them into the well-known ~/.copilot discovery folders that VS Code, the GitHub Copilot CLI, and Claude Code read.' PowerShellVersion = '5.1' FunctionsToExport = @('Get-CopilotAtelierVersion','Install-CopilotAtelier','Update-CopilotAtelier') CmdletsToExport = @() VariablesToExport = @() AliasesToExport = @() PrivateData = @{ PSData = @{ Tags = @( 'Copilot' 'GitHubCopilot' 'VSCode' 'Agents' 'Skills' 'Prompts' 'Instructions' 'Hooks' 'AI' 'Windows' 'Linux' 'MacOS' ) LicenseUri = 'https://github.com/raandree/CopilotAtelier/blob/main/LICENSE' ProjectUri = 'https://github.com/raandree/CopilotAtelier' IconUri = 'https://raw.githubusercontent.com/raandree/CopilotAtelier/main/assets/CA-glyph-on-light.png' Prerelease = 'preview0012' ReleaseNotes = '## [4.0.0-preview0012] - 2026-08-25 ### Added - **`copilot-usage-stats` converts tokens into AI credits and dollars** (2026-08-25). The Skill shipped hours earlier stating that the `cost` column "is not populated for subscription-billed requests" and stopping there, which left the question a user actually asks — what did this cost — unanswered and quietly wrong on two counts. GitHub moved to usage-based billing on 2026-06-01: an interaction is priced per token by model and converted to GitHub AI Credits at 1 credit = $0.01, so money is derivable from exactly the columns the Skill already read. And `cost` is not an unpopulated dollar figure at all — the one non-zero row in this repository reads `0.33` against a Claude Haiku 4.5 session, which is precisely that model''s legacy premium-request multiplier, so anything presenting the column as spend reports a request count in a currency symbol. Step 5 carries the conversion, and its whole reason for existing is one arithmetic trap: because `input_tokens` already contains `cache_read_tokens`, billing the full input at the input rate charges cached tokens at ten times their rate. On this repository''s own numbers that is the difference between $71.45 and roughly $450 — cache reads are 95.6 % of input in an agentic workload, so the error is not a rounding difference but an order of magnitude. Rates are fetched from [Models and pricing](https://docs.github.com/en/copilot/reference/copilot-billing/models-and-pricing) rather than quoted from memory, because they carry expiring promotional footnotes and models enter and leave the table. Four honesty constraints ship with it: recorded cache writes are zero where the store logged reads but no writes, so the figure is a floor; a model missing from the table is left unpriced and bounded rather than given a neighbour''s rate; promotional rates expire; and Pro/Pro+ subscribers who stayed on legacy annual request-based billing are billed by multiplier, for whom a token-derived figure is not their bill at all. The `description` widened to cover the conversion, so the trigger set gained two positives for credit and dollar phrasing and a `should upgrade to Pro+ or Max` negative that holds the line between measuring what was consumed and advising which plan to buy. - **`copilot-usage-stats` Skill and the `/usage` Prompt** (2026-08-25). "How many tokens has this project consumed?" had no answer that survived being asked twice, and the obvious design — a hook that tallies usage as turns complete — cannot be built. Four sources were checked before anything was written: no hook event carries usage or a model, on any of the eight (`PreToolUse` through `PreCompact`); the transcript JSONL a `Stop` hook could parse records `assistant.turn_end` as `{"turnId":"0"}` and nothing else; and the local `session-store.db` schema is `sessions`, `turns`, `session_files`, `session_refs`, `checkpoints`, with no `events` table and no token column anywhere. Token data exists only in the cloud store, reachable only through `copilot_sessionStoreSql` — so the answer is a Skill the model loads on any phrasing, not a command the user has to remember, and a Prompt on `Ctrl+K U` for the deterministic one-keystroke path. Two measured facts are what make the Skill worth loading rather than improvising the query. `input_tokens` **already contains** `cache_read_tokens`, shown by a per-call sequence where each call''s `cache_read` is the previous call''s `input` less a few tokens (89,097 → 89,754/89,094 → 90,950/89,751); adding the two, which is the natural reading of two adjacent columns, roughly doubles the reported figure, and reporting the raw 88 M input for this repository without splitting off the 84.5 M of cache reads describes one conversation being re-read as if it were fresh work. And `sessions.repository` is not normalized — this repository alone occupies `https://github.com/raandree/CopilotAtelier.git`, `https://github.com/raandree/CopilotAtelier`, and `raandree/CopilotAtelier`, the last with `cwd` set and the first two with it empty — so an equality filter silently drops most of a project''s history and returns a confident, small, wrong number. The Skill matches the bare name against both columns with `ILIKE` and folds the spellings before presenting a total. Scope is deliberately narrow: this reports, `chronicle` advises. `cost-tips` keeps token-reduction recommendations, standups, and session search; the six near-miss negatives in the trigger set are drawn from `chronicle`, `agent-evals`, `subagent-dispatch`, and `long-running-job-monitor` so the boundary is measured rather than asserted. The `cost` column is documented as unreportable rather than shown — it is `0` for every subscription-billed row, and a spend figure of zero is worse than none. The Memory Bank had a deterministic entry gate and no exit gate. `SessionStart` probes for the index, but the only durable write point is Post-flight, which runs "before ending the reply" — so a turn compacted mid-run never reaches it and everything the run learned goes with the conversation. The failure is quiet in the worst way: the summary that replaces the transcript still reports that Pre-flight ran, so the agent believes it holds `activeContext.md` when it does not, and nothing re-applies the routes. Every comparable system treats this as the primary threat — Anthropic injects *ASSUME INTERRUPTION: Your context window might be reset at any moment* into the memory tool''s system prompt, Cline tells the user to update the memory bank before the window fills, Claude Code re-reads the project `CLAUDE.md` from disk after `/compact` — while this repository covered it in one Prompt''s bespoke section, one manually invoked `/session-handoff`, and the `subagent-dispatch` ledger. All model judgement, none general, and the handoff has to be requested *before* saturation, which is exactly what a mid-turn agent will not do. [`Hooks/scripts/Write-CompactionCheckpoint.ps1`](Hooks/scripts/Write-CompactionCheckpoint.ps1) now writes `.memory-bank/session/compaction-<UTC>Z.md` before the truncation, carrying the trigger, transcript path, branch, commit, and changed paths, plus a resume protocol. What the hook cannot do is stated rather than papered over: `PreCompact` supports the common output format only — no `additionalContext` — so nothing it emits reaches the post-compaction context. The model-facing half is a *Compaction recovery* section in [`Instructions/preflight.instructions.md`](Instructions/preflight.instructions.md), which survives by construction because Instructions are re-sent with every request. Payload values are flattened and stripped before they enter a file an agent reads back, every failure path exits `0` so a hook fault cannot block compaction, and a workspace without a Memory Bank gets no directory — creating one stays reserved for the `memory-bank` Skill. - **Release-tag parity gate** (2026-08-25). Two releases shipped without a changelog section and nothing noticed, because the only thing that reads the release history is [`tests/PluginManifest.Tests.ps1`](tests/PluginManifest.Tests.ps1), and it reads the changelog rather than what was actually published. It now reads both. Every non-preview tag reachable from `HEAD` must have a matching `[x.y.z]` release section, so an unmerged rollover pull request turns `main` red instead of accumulating in silence. One exemption is load-bearing: a tag pointing at `HEAD` is skipped. On a tag push the `test` job runs before `deploy`, so at that instant the tag exists and its section cannot — `Create_ChangeLog_GitHub_PR` only runs after the release is published — and a strict gate would deadlock every release on itself. The exemption lapses the moment one commit lands on top, which is the earliest point at which the rollover *could* have been merged. Shown to reject before it was accepted: against the unfixed changelog the run was 8 passed, 3 failed, naming `v3.0.0` and `v3.1.0` and telling the reader which branch to merge; fixed, 12 of 12 pass. A companion assertion settles a question that had been left open — `plugin.json.version` is `major.minor.patch` and never a pre-release, because the field is committed, only moves on a release rollover, and is compared as an opaque string by plugin loaders, where `4.0.0-preview0007` sorts after `4.0.0` and would suppress the update to the real release. - **README catalogue gate** (2026-08-24). `AGENTS.md` has required a *Available Skills* row in every Skill''s atomic change set since 2026-08-12, but nothing checked it, and the drift that accumulated in the meantime was invisible: 36 rows against 45 shipped Skills. [`tests/SkillCatalogue.Tests.ps1`](tests/SkillCatalogue.Tests.ps1) closes it in both directions — every shipped Skill has a row, every row names a Skill that still ships, and every row carries a description. It parses the `## Available Skills` section rather than the whole file, because README holds other tables whose first cell is bold too and a whole-file scan reads `**Agents**` and `**Instructions**` as Skills. A count assertion guards the parser itself, so a moved heading fails loudly instead of passing with zero cases. Shown to reject before it was accepted: with one row removed the run is 133 passed, 1 failed, naming `agent-evals has a catalogue row`; restored, 136 of 136 pass. - **`brand-logo` Prompt** (2026-08-14). `brand-logo-system` answers "how do I build the asset set" but nothing started the conversation, and the first question an identity task needs — what should the mark actually show — is the one an agent is most likely to skip and guess. The Prompt front-loads it: search the repository for an existing mark first and, when one is found, ask only whether to keep, refine, or replace it rather than interviewing the user about a decision the repository already made; otherwise interview in two `vscode_askQuestions` clusters covering subject, visual treatment, character, colour source, wordma' } } } |