From 58be80882376f235c00b05b302501e276cbe145e Mon Sep 17 00:00:00 2001 From: Chris Titus Date: Wed, 1 Jul 2026 13:03:30 -0500 Subject: [PATCH] feat: Add AGENTS.md and SPEC.md for project guidelines and instructions --- AGENTS.md | 185 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ SPEC.md | 105 +++++++++++++++++++++++++++++++ 2 files changed, 290 insertions(+) create mode 100644 AGENTS.md create mode 100644 SPEC.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..072010a5 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,185 @@ +# AGENTS.md + +Drop-in operating instructions for coding agents. Read this file before every task. + +**Working code only. Finish the job. Plausibility is not correctness.** + +This repository follows the AGENTS.md convention: these instructions are for Codex, Claude Code, Cursor, Windsurf, Copilot, Aider, Devin, Amp, and other coding agents that read `AGENTS.md`. + +## 0. Non-Negotiables + +These rules override everything else in this file when in conflict: + +1. **Do not edit `winutil.ps1` directly.** It is generated build output. Change source files and compile. +2. **Do not commit `winutil.ps1`.** It is ignored locally and generated by GitHub Actions for releases. +3. **Never fabricate.** Do not invent file paths, function names, command output, test results, commit hashes, or API behavior. Read the file or run the command. +4. **Disagree when the premise is wrong.** Say what is wrong before acting on it. +5. **Stop when genuinely ambiguous.** If two interpretations would produce materially different diffs, ask before editing. +6. **Touch only what the task requires.** No drive-by refactors, formatting sweeps, or unrelated cleanup. +7. **Verify before saying done.** A plausible-looking diff is not proof. + +## 1. Project Context + +WinUtil is a Windows PowerShell utility with a WPF interface. The repository is maintained as modular source, but the distributed artifact is one compiled PowerShell script. + +### Stack + +- Language: Windows PowerShell / PowerShell. +- UI: WPF via `xaml/inputXML.xaml`. +- Configuration: JSON files under `config/`. +- Tests: Pester tests under `pester/`. +- Lint: PowerShell Script Analyzer with settings in `lint/PSScriptAnalyser.ps1`. +- Docs: Hugo site under `docs/`. +- Release artifact: generated root `winutil.ps1`. + +### Key Commands + +- Compile: + ```powershell + .\Compile.ps1 + ``` +- Compile and run GUI: + ```powershell + .\Compile.ps1 -Run + ``` +- Run tests: + ```powershell + Invoke-Pester -Path 'pester/*.Tests.ps1' -Output Detailed + ``` +- Run Script Analyzer with project settings when available: + ```powershell + Invoke-ScriptAnalyzer -Path . -Settings .\lint\PSScriptAnalyser.ps1 -Recurse + ``` + +Prefer the narrowest useful verification while iterating. Use the full relevant check before finishing. + +## 2. Source Of Truth + +Make durable changes only in files consumed by `Compile.ps1` or in documentation/test files: + +- `scripts/start.ps1` for startup/bootstrap code. +- `functions/public/*.ps1` for UI-facing and user-facing workflows. +- `functions/private/*.ps1` for internal helpers. +- `config/*.json` for applications, tweaks, features, DNS, presets, navigation, themes, and related declarative data. +- `xaml/inputXML.xaml` for the WPF UI layout. +- `tools/autounattend.xml` for the embedded unattended Windows setup template. +- `scripts/main.ps1` for the final entrypoint and GUI initialization logic appended during compile. +- `pester/*.Tests.ps1` for automated checks. +- `docs/` for Hugo documentation. + +If behavior changes require the compiled script to change, update these source files and run `.\Compile.ps1` only to verify generation. + +## 3. Build Model + +`Compile.ps1` combines the repository sources into `winutil.ps1` in this order: + +1. Read `scripts/start.ps1` and replace `#{replaceme}` with the current `yy.MM.dd` build date. +2. Append every file under `functions/` recursively. +3. Convert each `config/*.json` file into embedded `$sync.configs` objects. +4. Special-case `config/applications.json` so keys receive the `WPFInstall` prefix in compiled config. +5. Embed `xaml/inputXML.xaml` into `$inputXML`. +6. Embed `tools/autounattend.xml` into `$WinUtilAutounattendXml`. +7. Append `scripts/main.ps1`. +8. Write the result to root `winutil.ps1`. + +Because the final script is concatenated, do not rely on runtime module imports or source-relative dot-sourcing unless the compiled script will also contain the required code/data. + +## 4. Before Editing + +- State the plan in one or two sentences before editing. For non-trivial work, include the verification you intend to run. +- Read the files you will touch and the files that call them. +- Match existing patterns even when a different greenfield design would be cleaner. +- Surface assumptions when they affect behavior, compatibility, or user data. +- If two approaches have meaningful tradeoffs, name them before choosing. Trivial tasks can proceed directly. + +## 5. Coding Guidelines + +- Prefer the minimum code that solves the stated problem. +- Keep PowerShell functions in one function file when practical, with the file name matching the primary function name. +- Use approved PowerShell verb-noun names and follow the existing `WPF` / `WinUtil` naming conventions. +- Keep UI event handler names aligned with XAML element names. A button named `WPFExampleButton` is typically handled by `Invoke-WPFExampleButton`. +- Use `$sync` for shared state and UI references, consistent with the existing runspace model. +- Update WPF controls through the UI dispatcher when running work in a background runspace. +- Keep config-driven features in JSON when they fit the existing schema instead of hard-coding lists in PowerShell. +- Preserve undo/original-state data for tweaks so users can reverse changes. +- Do not add abstractions, configurability, hooks, or "future extensibility" unless the task needs them now. +- Clean up orphans created by your own changes, such as unused variables or functions made obsolete by the edit. +- Avoid broad formatting-only edits, especially in JSON config files, XAML, docs, and generated output. + +## 6. Runtime And Safety Rules + +- WinUtil performs system-level Windows changes. Treat registry, services, AppX removal, package manager, Windows Update, ISO, and unattended setup changes as high-risk. +- Prefer existing helper functions for WinGet, Chocolatey, registry, services, progress, and UI updates. +- Keep tweaks reversible where the schema supports it by including original values or original states. +- Never modify a user's original ISO in-place; follow existing copy/mount/export patterns. +- Avoid storing credentials, secrets, or machine-specific paths in repo files. +- Preserve logging and user feedback patterns for long-running or destructive operations. + +## 7. Surgical Changes + +- Do not improve adjacent code, comments, formatting, imports, or docs unless required. +- Do not refactor working code because you are already in the file. +- Do not delete pre-existing dead code unless asked; mention it in the summary if relevant. +- Keep diffs reviewable. Every changed line should trace to the user's request. +- If a change starts spreading across unrelated areas, pause and reassess the plan. + +## 8. Verification + +Define success in terms that can be checked, then check it. + +- For compile/build changes, run `.\Compile.ps1`. +- For GUI behavior changes, run `.\Compile.ps1 -Run` when practical and verify the affected path manually. +- For config changes, run the compile check and relevant Pester tests. +- For function changes, run the relevant Pester tests or add/update focused tests when practical. +- For docs-only changes, proofread the changed files and skip runtime tests unless docs generation is affected. +- Read command output. Do not report tests as passing unless they actually passed. +- If verification fails, fix the cause rather than weakening the test. + +If a check cannot be run, say exactly why and what residual risk remains. + +## 9. Generated Files And Git Hygiene + +- Treat local `winutil.ps1` changes as disposable compile output. +- Never stage or commit `winutil.ps1`, `docs/public/`, `docs/resources/`, `binary/`, editor folders, or other ignored build artifacts. +- Do not remove `.gitignore` rules that keep generated artifacts out of Git. +- Before finishing, check `git status --short` and separate your changes from pre-existing user changes. +- Do not revert user changes unless explicitly asked. +- Commit messages, when requested, should be descriptive: short subject under 72 characters, body explaining why when needed. + +## 10. Documentation Expectations + +- Update `docs/content/` when user-facing behavior changes. +- Update developer docs when architecture, build flow, config schema, or contribution workflow changes. +- Keep README changes brief and high-level. +- Put detailed user and developer documentation under `docs/`. +- Keep `SPEC.md` aligned with build/runtime contract changes. + +## 11. Communication Style + +- Be direct and concise. Start with the answer or action. +- No flattery, filler, ceremonial closings, or fake certainty. +- Use bullets only when they improve scanning. +- Report what changed, how it was verified, and anything not done. +- If the user asks for a review, lead with findings and file/line references. + +## 12. When To Ask + +Ask before proceeding when: + +- The request has two plausible interpretations and the choice materially changes behavior or files touched. +- The change affects release generation, generated artifacts, migrations, or high-risk Windows behavior in a way the user did not specify. +- You need credentials, secrets, production resources, or access you do not have. +- The user's stated goal conflicts with the literal request. + +Proceed without asking when: + +- The task is trivial and reversible. +- Ambiguity can be resolved by reading the code or running a local command. +- The user already answered the question in this session. + +## 13. Project Learnings + +When the user corrects an agent approach, add or tighten one concrete rule here before ending the session. Keep this section short and prune rules that no longer matter. + +- Keep `winutil.ps1` generated-only: change source files, compile to verify, and never stage the generated script. + diff --git a/SPEC.md b/SPEC.md new file mode 100644 index 00000000..780dc636 --- /dev/null +++ b/SPEC.md @@ -0,0 +1,105 @@ +# SPEC.md + +## Project Contract + +WinUtil is a Windows PowerShell utility with a WPF interface. The repository is maintained as modular source files, but the released artifact is a single generated `winutil.ps1` script. + +The compiled `winutil.ps1` is not source code for editing or review. It is generated by `Compile.ps1` and produced during release automation. All durable changes must be made to the source files that feed the compiler. + +## Goals + +- Provide a single-script Windows utility that can be launched from PowerShell. +- Keep development modular enough for contributors to work on functions, config, UI, docs, and tooling independently. +- Make install, tweak, feature, repair, update, and ISO workflows discoverable from the WPF UI. +- Keep common lists and options declarative in JSON config where possible. +- Preserve a repeatable compile process so local builds and GitHub Actions builds produce the distributable script from the same inputs. + +## Non-Goals + +- `winutil.ps1` is not hand-maintained. +- The project is not structured as a PowerShell module at runtime. +- The GUI is not a separate packaged desktop application in this repository's normal release path. +- Generated files should not be reviewed as source changes. + +## Repository Layout + +- `Compile.ps1`: build script that creates `winutil.ps1`. +- `scripts/start.ps1`: startup/bootstrap segment used at the beginning of the compiled script. +- `scripts/main.ps1`: main entrypoint appended at the end of the compiled script. +- `functions/public/`: public/UI-facing PowerShell functions. +- `functions/private/`: internal helper PowerShell functions. +- `config/`: JSON configuration consumed at compile time and embedded into `$sync.configs`. +- `xaml/inputXML.xaml`: WPF UI markup embedded into the compiled script. +- `tools/autounattend.xml`: unattended setup XML embedded for Windows ISO workflows. +- `pester/`: Pester tests for config and function checks. +- `lint/PSScriptAnalyser.ps1`: PowerShell Script Analyzer settings. +- `docs/`: Hugo documentation site. +- `winutil.ps1`: ignored generated build artifact. + +## Compile Specification + +`Compile.ps1` must produce a standalone root `winutil.ps1` by combining all required project files. + +The compile flow is: + +1. Initialize shared state with `$sync = [Hashtable]::Synchronized(@{})` and `$sync.configs = @{}`. +2. Read `scripts/start.ps1`. +3. Replace `#{replaceme}` in startup code with the current `yy.MM.dd` build date. +4. Append raw content from all files under `functions/` recursively. +5. For every file in `config/`, parse JSON and embed it into `$sync.configs.`. +6. Special-case `config/applications.json` so application keys are emitted with the `WPFInstall` prefix. +7. Embed `xaml/inputXML.xaml` as `$inputXML`. +8. Embed `tools/autounattend.xml` as `$WinUtilAutounattendXml`. +9. Append `scripts/main.ps1`. +10. Write the combined script to `winutil.ps1`. +11. If `-Run` is supplied, execute the generated script. + +The generated script must have everything it needs from repository sources embedded or appended by this process. + +## Runtime Model + +- WinUtil runs in PowerShell on Windows and uses WPF for the UI. +- Shared mutable state is stored in `$sync`, including configs, UI element references, runspace state, selections, and progress. +- Long-running operations should use runspaces or existing async patterns so the UI remains responsive. +- UI updates from background work must be dispatched back to the WPF UI thread. +- Declarative features such as apps, tweaks, presets, DNS providers, and navigation should stay in `config/*.json` unless code is required. + +## UI And Event Contract + +- UI layout lives in `xaml/inputXML.xaml`. +- Named WPF controls are discovered and stored in `$sync`. +- Button/action wiring follows existing naming conventions, where an element named like `WPFThingButton` maps to a function named like `Invoke-WPFThingButton`. +- When adding controls, ensure the XAML name, config key, and PowerShell function names line up with the existing event system. + +## Configuration Contract + +Config files must remain valid JSON and compile cleanly through `ConvertFrom-Json`. + +`config/applications.json` defines installable applications. Each application entry should include the fields expected by tests and UI code, such as package manager IDs, category, display content, description, and link. + +`config/tweaks.json` defines Windows tweaks. Registry and service changes should include original values or original states when applicable so undo workflows can restore user systems. + +Preset and navigation files should reference valid config keys. Avoid renaming config keys unless all presets, UI references, docs, and code paths are updated together. + +## Safety Requirements + +- Registry, service, package manager, Windows Update, AppX removal, and ISO operations can affect the host system. Changes must be explicit, reversible where practical, and consistent with existing logging and confirmation patterns. +- Tweak changes should include undo metadata when the schema supports it. +- Package installation should prefer existing WinGet and Chocolatey helper functions. +- ISO workflows must not modify the user's original ISO file; they should work on copied/mounted content following existing patterns. + +## Testing And CI + +Expected validation for source changes: + +- `.\Compile.ps1` verifies the compiler can generate `winutil.ps1`. +- `.\Compile.ps1 -Run` compiles and launches the generated utility for manual GUI verification. +- `Invoke-Pester -Path 'pester/*.Tests.ps1' -Output Detailed` runs the Pester suite. +- GitHub Actions also runs a compile check and PowerShell Script Analyzer with `lint/PSScriptAnalyser.ps1`. + +The generated `winutil.ps1` may appear locally after compile. It remains ignored build output and must not be committed. + +## Release Artifact + +GitHub Actions is responsible for producing the release `winutil.ps1` from repository sources. A release should be considered valid only if the generated script came from the compile process, not from direct manual edits to `winutil.ps1`. +