CopilotAtelier.psd1

@{
    RootModule        = 'CopilotAtelier.psm1'

    # Replaced at build time by GitVersion.
    ModuleVersion     = '5.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   = 'preview0004'

            ReleaseNotes = '## [5.0.0-preview0004] - 2026-09-01

### Fixed

- **The mandatory disclaimer travelled into two signed submissions to a German tax office** (2026-08-31). [`com.github.copilot/agents/tax-researcher.agent.md`](com.github.copilot/agents/tax-researcher.agent.md) opened with "include this at the end of every substantive output", and the model did exactly that: an RDG and StBerG notice ended up below the signature block of two `Einspruchsbegründungen`, where [`skills/german-tax-research/SKILL.md`](skills/german-tax-research/SKILL.md) had forbidden it since the Skill was written. The defect surfaced only when the taxpayer had already printed and signed both letters.

  The two rules were both present and contradicted each other. The agent''s instruction was unqualified; the Skill''s fourth non-negotiable said submissions carry no internal caveats. An unqualified instruction in the agent body beats a rule three sections into a Skill, so the agent is where the fix belongs: the disclaimer now applies to chat replies and internal working papers, and never to a `Schriftsatz`, `Einspruch`, `Anlage`, `Eigenbeleg`, or `Erklärung` that a taxpayer signs. The reason is spelled out rather than asserted — in a letter the taxpayer signs, a notice disclaiming tax advice reads as if an unauthorised third party had drafted it.

  A rule nobody checks is a rule that fails silently, so both files now carry the check. The agent gains a marker sweep in phase 5 and an anti-pattern for shipping a `Schriftsatz` PDF without one. The Skill''s non-negotiable 4 names the production failure, lists the search terms — `StBerG`, `RDG`, `Steuerberatung`, `intern`, `Entwurf`, `Prüfvermerk`, `TODO` — and requires the sweep **twice**: once against the Markdown and once against the rendered PDF''s text layer, because a template or a CSS rule can reintroduce what the source no longer shows. The existing `Marker sweep` verification item is extended accordingly.

### Changed

- **`german-tax-research` gains a disclosure economy** (2026-08-31). A `Begründung` addressed to a tax office had been disclosing which receipts were missing for positions nobody had questioned, explaining at length why items were *not* claimed, and conceding reductions the office had not proposed. Each sentence was true; together they handed the examiner a worklist he had not written.

  The new section separates two duties that get conflated. `§ 150 Abs. 2 AO` requires the declared bases of taxation to be complete and true; it does not require a self-assessment of how strong the evidence behind them is. `§§ 90, 97 AO` oblige cooperation and production — on request, and under the `Belegvorhaltepflicht` that request often never comes. One test decides every sentence: does it support an amount that is actually declared?

  Estimates, deviations from the transmitted return, method changes, `§ 153 AO` corrections, and positions maintained against a contrary document must still be disclosed — silence there is the real risk. What must not be volunteered is the evidentiary weakness of a claimed and consistent position, any reasoning for a position that is not claimed at all, the fact that a figure rests on the taxpayer''s own statement where no third-party document could exist, speculation drawn from a bank entry, anticipatory concessions, and promises of documents nobody asked for. Three exceptions keep a non-claimed item in the letter: a cross-year inconsistency the office would otherwise spot, a double-deduction reproach worth forestalling, and a correction against the taxpayer. Two anti-rationalizations, three red flags, a `Disclosure sweep` verification item, and an anti-pattern make it checkable; the `tax-researcher` agent gains the matching phase-5 probe and four German anti-patterns.

### Changed

- **The Software Engineer agent no longer hands work to `security-reviewer` on its own judgement** (2026-08-28). [`com.github.copilot/agents/software-engineer.agent.md`](com.github.copilot/agents/software-engineer.agent.md) gains an explicit independent review switch that is `off` by default, so a routine change now ends with the agent''s own validation and self-review instead of a subagent dispatch that costs minutes of latency per turn.

  The old rule read "request an independent review with a subagent for high-risk work" and then listed security or identity boundaries, destructive operations, persistence, concurrency, public APIs, cross-module contracts, and "a large unfamiliar diff". In an agent-customization repository almost every change matches at least one of those, and the `Design and security` rule pointing at `agent-security-review` for "agents, LLM-backed features, RAG, or MCP servers" matches the rest — so the risk-scaled default behaved as an unconditional handover. The trigger list survives unchanged; what changed is what it triggers.

  The switch is user-set, not model-set: `review: on` requests one independent review of the finished change, `review: auto` restores the previous risk-scaled dispatch, and `review: off` is the default. Plain language and the existing *Run Security Review* handoff button both count as `on`, so the fast path stays available without new syntax to learn. `argument-hint` advertises it in the picker.

  Turning the default off without losing the signal needed one more piece. With the switch off the agent still evaluates the same risk list, but it names the risk instead of reviewing it: the work finishes and the closing line recommends `review: on` and states why. [`com.github.copilot/rules/postflight.instructions.md`](com.github.copilot/rules/postflight.instructions.md) gains the matching clause, because the shared Definition of Done gate demanded that independent review "was completed" — a contradiction the model would otherwise have resolved by dispatching anyway. The requirement stands for every other agent; only the deferral path is now named.

  [`com.github.copilot/agents/software-engineer-contoso.agent.md`](com.github.copilot/agents/software-engineer-contoso.agent.md) is unaffected by design. Its inlined base body is re-synced, but the overlay pins the switch to `on` for security-relevant diffs, new dependencies, new network paths, and first-time repositories, and states that a `review: off` request downgrades nothing there — an overlay that only adds constraints must not inherit a relaxation. [`tests/SoftwareEngineerAgent.Tests.ps1`](tests/SoftwareEngineerAgent.Tests.ps1) covers the default, the three switch values, and the `argument-hint`, so the auto-handover cannot come back silently.

### Added

- **`elster-form-capture`, a Skill for driving the Mein ELSTER web form by machine** (2026-08-31). Three full capture runs across two assessment years produced the material: [`skills/elster-form-capture/SKILL.md`](skills/elster-form-capture/SKILL.md) fills a German income tax return field by field while the taxpayer signs in, reviews, and presses Send.

  The boundary is legal, not technical. Transmission is the taxpayer''s declaration of knowledge under `§ 150 Abs. 2 S. 1 AO`, so filling fields is assistance and sending is not delegable — *Versenden des Formulars* is a non-negotiable the Skill never presses. It handles no credentials either: the user authenticates and shares the page.

  One fact carries the whole Skill. The official ERiC field numbers behind `name="fields[…]"` are stable across assessment years; the `Teilseite` and `Zeile` numbers are not. The `Anlage V` was reorganised for 2023 and renumbered *again* for 2024 — apportioned costs moved from sub-page 12 to 13, the result and allocation from 17 to 18, and sub-letting left the attachment entirely for a new `Anlage V-Sonstige` — while not one `data-eru-name` changed. So the Skill addresses fields by Kennzahl, verifies by sub-page heading, and treats a line number from a guide written for another year as a claim to be checked. [`references/feldkarte-est.md`](skills/elster-form-capture/references/feldkarte-est.md) carries the harvested numbers for `Anlage V`, `V-Sonstige`, `N`, and `Vorsorgeaufwand`, with the 2023-to-2024 movements tabulated above them.

  The 29 gotchas are corrections, not advice; each one cost a failed attempt. The three that generalise beyond ELSTER: a `page.goto()` discards a select box the server has not yet acknowledged, because the `beforeunload` dialog takes the change with it — three running numbers were set in a loop and only the last survived. The *add* button of a sub-form shares its id prefix with *edit*, differing only in a trailing index, so `.first()` silently overwrote the first foreign country with the second. And a value transferred as eData can itself be the error: an employer reported 0.00 € for statutory health insurance, and the field had to be *emptied* rather than left at zero.

  The finding that justifies the whole approach is not the typing. Driving the form mechanically turned out to be the fastest audit of the capture guide that feeds it — it caught a wrong postcode (the insolvent developer''s address, not the property''s), a stale line reference, and, through a machine comparison of 52 target amounts against the summary page, 1,330 € of deductions that a status table already recorded as captured. Hence the rule that the final check is a comparison and never a reading: values produced by someone else are demonstrably reviewed less carefully than values one typed.

  [`skills/agent-evals/assets/trigger-queries.elster-form-capture.json`](skills/agent-evals/assets/trigger-queries.elster-form-capture.json) carries ten positives in both German and English and ten near-miss negatives drawn from the neighbours the Skill must not displace: substantive deductibility and `Einspruch` drafting belong to `german-tax-research`, login persistence to `authenticated-web-extraction`, receipt reading to `pdf-to-markdown` and `xlsx-to-markdown`, the `Anlagen` bundle to `evidence-package-assembly`. "Fill in this PDF form" is included deliberately as the closest f'

        }
    }
}