feat: Add AGENTS.md and SPEC.md for project guidelines and instructions

This commit is contained in:
Chris Titus
2026-07-01 13:03:30 -05:00
parent c7dfbeb7fe
commit 58be808823
2 changed files with 290 additions and 0 deletions
+185
View File
@@ -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.
+105
View File
@@ -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.<basename>`.
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`.