Compare commits
11
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a95d6aef9f | ||
|
|
4316fa3c67 | ||
|
|
8610dcf348 | ||
|
|
13e2dbbea0 | ||
|
|
396f62a503 | ||
|
|
b65af63e7e | ||
|
|
0189323e8f | ||
|
|
54820797fa | ||
|
|
30a057c41b | ||
|
|
8b5a7e39b3 | ||
|
|
25bc29b8a4 |
No files matched your search
@@ -0,0 +1,15 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: FrauJulian
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
||||
polar: # Replace with a single Polar username
|
||||
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
|
||||
thanks_dev: # Replace with a single thanks.dev username
|
||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
||||
@@ -0,0 +1,106 @@
|
||||
name: Redirect contributions to Gitea
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened, reopened]
|
||||
pull_request_target:
|
||||
types: [opened, reopened]
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
concurrency:
|
||||
group: migrate-${{ github.event_name }}-${{ github.event.issue.number || github.event.pull_request.number }}
|
||||
|
||||
env:
|
||||
GITEA_API_URL: https://git.lechner-systems.at/api/v1
|
||||
GITEA_REPOSITORY: FrauJulian/MyAiConfiguration
|
||||
|
||||
jobs:
|
||||
migrate-issue:
|
||||
if: github.event_name == 'issues'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Migrate issue and close
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
number="$(jq -r '.issue.number' "$GITHUB_EVENT_PATH")"
|
||||
title="$(jq -r '.issue.title' "$GITHUB_EVENT_PATH")"
|
||||
body="$(jq -r '.issue.body // ""' "$GITHUB_EVENT_PATH")"
|
||||
author="$(jq -r '.issue.user.login' "$GITHUB_EVENT_PATH")"
|
||||
source_url="$(jq -r '.issue.html_url' "$GITHUB_EVENT_PATH")"
|
||||
github_api="${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}"
|
||||
migrated_url="$(
|
||||
curl --fail --silent --show-error \
|
||||
--header "Authorization: Bearer ${GITHUB_TOKEN}" \
|
||||
--header "Accept: application/vnd.github+json" \
|
||||
"${github_api}/issues/${number}/comments?per_page=100" |
|
||||
jq -r '[.[] | select(.user.login == "github-actions[bot]" and (.body | startswith("Migrated to Gitea: ")))] | first | .body // "" | sub("^Migrated to Gitea: "; "")'
|
||||
)"
|
||||
|
||||
if [ -z "$migrated_url" ]; then
|
||||
migrated_body="${body}
|
||||
|
||||
---
|
||||
Originally opened by @${author} on GitHub: ${source_url}"
|
||||
|
||||
jq -n \
|
||||
--arg title "$title" \
|
||||
--arg body "$migrated_body" \
|
||||
'{title: $title, body: $body}' > gitea-request.json
|
||||
|
||||
curl --fail-with-body \
|
||||
--request POST \
|
||||
--header "Authorization: token ${GITEA_TOKEN}" \
|
||||
--header "Content-Type: application/json" \
|
||||
--data @gitea-request.json \
|
||||
"${GITEA_API_URL}/repos/${GITEA_REPOSITORY}/issues" > gitea-response.json
|
||||
|
||||
migrated_url="$(jq -r '.html_url' gitea-response.json)"
|
||||
jq -n --arg body "Migrated to Gitea: ${migrated_url}" '{body: $body}' > github-comment.json
|
||||
curl --fail-with-body \
|
||||
--request POST \
|
||||
--header "Authorization: Bearer ${GITHUB_TOKEN}" \
|
||||
--header "Content-Type: application/json" \
|
||||
--data @github-comment.json \
|
||||
"${github_api}/issues/${number}/comments"
|
||||
fi
|
||||
|
||||
curl --fail-with-body \
|
||||
--request PATCH \
|
||||
--header "Authorization: Bearer ${GITHUB_TOKEN}" \
|
||||
--header "Content-Type: application/json" \
|
||||
--data '{"state":"closed","state_reason":"not_planned"}' \
|
||||
"${github_api}/issues/${number}"
|
||||
|
||||
redirect-pull-request:
|
||||
if: github.event_name == 'pull_request_target'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Redirect pull request and close
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
number="$(jq -r '.pull_request.number' "$GITHUB_EVENT_PATH")"
|
||||
github_api="${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}"
|
||||
|
||||
curl --fail-with-body \
|
||||
--request POST \
|
||||
--header "Authorization: Bearer ${GITHUB_TOKEN}" \
|
||||
--header "Content-Type: application/json" \
|
||||
--data '{"body":"Please open the Pull Request on Gitea"}' \
|
||||
"${github_api}/issues/${number}/comments"
|
||||
|
||||
curl --fail-with-body \
|
||||
--request PATCH \
|
||||
--header "Authorization: Bearer ${GITHUB_TOKEN}" \
|
||||
--header "Content-Type: application/json" \
|
||||
--data '{"state":"closed"}' \
|
||||
"${github_api}/pulls/${number}"
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
generated/
|
||||
*.log
|
||||
*.tmp
|
||||
*.bak
|
||||
backups/
|
||||
.env
|
||||
.env.*
|
||||
auth.json
|
||||
credentials.json
|
||||
secrets.json
|
||||
!.env.example
|
||||
@@ -0,0 +1 @@
|
||||
Read and follow `AI-Instructions.md` before working in this repository.
|
||||
@@ -0,0 +1,60 @@
|
||||
# AI instructions
|
||||
|
||||
This file contains maintenance instructions for this repository only. It is not
|
||||
part of the generated Codex or Claude Code configuration and must not be read
|
||||
or processed by build output.
|
||||
|
||||
## Architecture
|
||||
|
||||
Keep the architecture as:
|
||||
|
||||
`shared definitions -> client adapters -> generated output -> optional installation`
|
||||
|
||||
- Modify shared definitions first.
|
||||
- Keep adapters limited to client-specific formats and metadata.
|
||||
- Do not duplicate shared behavior in adapters.
|
||||
- Treat `generated/` as reproducible build output.
|
||||
- Maintain equivalent support for both Codex and Claude Code.
|
||||
- Keep technology-specific rules in separate files under `shared/rules/`.
|
||||
- Generate those rule files beside `AGENTS.md` and `CLAUDE.md`; load them only when their subject applies.
|
||||
|
||||
## Portability
|
||||
|
||||
- Design scripts, hooks, generated configuration, and installation behavior for both Windows and Linux.
|
||||
- Use cross-platform tools and paths where practical.
|
||||
- When platform-specific behavior is necessary, provide an equivalent implementation or a safe no-op for the other supported platform.
|
||||
- Provide equivalent native Bash (`.sh`) and PowerShell (`.ps1`) entry points for every script and hook.
|
||||
- Support Windows PowerShell 5.1 and newer on Windows, and PowerShell 7 (`pwsh`) on Linux. Keep shared PowerShell syntax compatible with 5.1; Windows must not require PowerShell 7.
|
||||
- Validate relevant changes on both supported platforms when practical.
|
||||
|
||||
## Language
|
||||
|
||||
Write all repository content, generated instructions, scripts, prompts, documentation, and user-facing script output in English.
|
||||
|
||||
## Workflow
|
||||
|
||||
- Run `scripts/build.ps1` to validate every project change before completion.
|
||||
- Rebuild generated output after semantic changes.
|
||||
- Run `scripts/doctor.ps1` when changes affect generated output, installation, client configuration, hooks, or environment validation.
|
||||
- Preserve backward compatibility where practical.
|
||||
- Keep changes focused on the requested configuration behavior.
|
||||
|
||||
## Instruction sources
|
||||
|
||||
- Define repository-maintenance rules only in `AI-Instructions.md`.
|
||||
- Keep the repository-root AGENTS.md and CLAUDE.md as pointer-only files.
|
||||
- Keep generated global instructions in shared/global-instructions.md; the build copies that file into each generated client package.
|
||||
- Do not include `AI-Instructions.md` in generated output.
|
||||
|
||||
## Installation and security
|
||||
|
||||
- Do not install global configuration automatically.
|
||||
- Perform global installation only after explicit user instruction, using `scripts/install.ps1` so replaced managed files are backed up.
|
||||
- Do not add project-specific rules, secrets, credentials, authentication state, or generated runtime state.
|
||||
|
||||
## Version control
|
||||
|
||||
- Never commit changes unless explicitly instructed.
|
||||
- Preserve unrelated user changes.
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
Read and follow `AI-Instructions.md` before working in this repository.
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 Julian Lechner
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,183 @@
|
||||
# My AI Configuration
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
[](LICENSE)
|
||||
|
||||
`MyAiConfiguration` is a version-controlled global user configuration for OpenAI Codex and Claude Code.
|
||||
|
||||
It keeps rules, skills, agents, hooks, and orchestration guidance in shared source files. Client adapters turn those files
|
||||
into platform-specific packages that can be inspected before they are installed.
|
||||
|
||||
## Features
|
||||
|
||||
- One shared source of truth for Codex and Claude Code.
|
||||
- Separate generated packages for Windows and Linux.
|
||||
- Native PowerShell 5.1 and Bash scripts.
|
||||
- Interactive installation for Codex, Claude Code, or both.
|
||||
- Dry-run support and timestamped backups of replaced managed files.
|
||||
- Shared safety, notification, validation, and status-line hooks.
|
||||
- User-level plugin installation and updates for Ponytail, i-have-adhd, Superpowers, and Context7.
|
||||
|
||||
## Architecture
|
||||
|
||||
```text
|
||||
shared definitions -> client adapters -> generated packages -> user installation
|
||||
```
|
||||
|
||||
| Directory | Purpose |
|
||||
| --- | --- |
|
||||
| `shared/` | Client-independent rules, agents, skills, hooks, status lines, and global instructions. |
|
||||
| `adapters/` | Codex and Claude Code formats, settings, templates, and the plugin manifest. |
|
||||
| `generated/` | Reproducible Windows and Linux packages. This directory is ignored by Git. |
|
||||
| `scripts/` | Build, installation, diagnosis, and platform validation entry points. |
|
||||
| `docs/` | Focused documentation about the configuration design. |
|
||||
|
||||
The build creates:
|
||||
|
||||
```text
|
||||
generated/
|
||||
├── codex-windows/
|
||||
├── claude-windows/
|
||||
├── codex-linux/
|
||||
└── claude-linux/
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
- Windows PowerShell 5.1 or newer on Windows.
|
||||
- Bash on Linux.
|
||||
- The Codex and Claude Code CLIs for the clients that should be installed or diagnosed.
|
||||
- Network access for plugin installation and updates.
|
||||
|
||||
The Bash scripts do not require PowerShell. The PowerShell scripts remain compatible with Windows PowerShell 5.1;
|
||||
PowerShell 7 can also run them.
|
||||
|
||||
## Build
|
||||
|
||||
Run the matching command from the repository root:
|
||||
|
||||
Powershell: (Windows)
|
||||
```powershell
|
||||
.\scripts\build.ps1
|
||||
```
|
||||
|
||||
Bash: (Linux)
|
||||
```bash
|
||||
./scripts/build.sh
|
||||
```
|
||||
|
||||
Every repository change must pass the build before completion. Building only writes reproducible files below
|
||||
`generated/`; it does not modify global user configuration.
|
||||
|
||||
## Installation
|
||||
|
||||
The installer runs a fresh build and then asks for the target platform and client. Selecting Linux or Windows chooses
|
||||
the generated package format; installation always targets the current user's home directory.
|
||||
|
||||
Preview an installation without changing user files or plugins:
|
||||
|
||||
Powershell: (Windows)
|
||||
```powershell
|
||||
.\scripts\install.ps1 -DryRun
|
||||
```
|
||||
|
||||
Bash: (Linux)
|
||||
```bash
|
||||
./scripts/install.sh --dry-run
|
||||
```
|
||||
|
||||
Install the selected configuration:
|
||||
|
||||
Powershell: (Windows)
|
||||
```powershell
|
||||
.\scripts\install.ps1
|
||||
```
|
||||
|
||||
Bash: (Linux)
|
||||
```bash
|
||||
./scripts/install.sh
|
||||
```
|
||||
|
||||
Existing managed files receive timestamped backups before replacement. Unrelated files are left untouched. Selecting
|
||||
Codex also installs shared skills to `.agents/skills`. A normal installation ensures configured plugins are present and
|
||||
updates plugins that are already installed.
|
||||
|
||||
Run the same installation command whenever the repository configuration should be updated. There is no separate update
|
||||
script.
|
||||
|
||||
## Doctor
|
||||
|
||||
Check client availability, generated packages, source directories, hooks, and installed managed files:
|
||||
|
||||
Powershell: (Windows)
|
||||
```powershell
|
||||
.\scripts\doctor.ps1
|
||||
```
|
||||
|
||||
Bash: (Linux)
|
||||
```bash
|
||||
./scripts/doctor.sh
|
||||
```
|
||||
|
||||
The doctor reports concise `PASS`, `WARN`, and `FAIL` results without reading or printing credentials.
|
||||
|
||||
## Configuration
|
||||
|
||||
Codex receives global instructions, rules, skills, agent TOML files, hooks, and `config.toml`. Its defaults keep writes
|
||||
workspace-scoped and use automatic review for eligible escalation requests.
|
||||
|
||||
Claude Code receives the equivalent global instructions, rules, skills, agents, hooks, and `settings.json`. Its generated
|
||||
settings use the supported automatic permission mode where available.
|
||||
|
||||
Both clients receive the same logical agent roles:
|
||||
|
||||
- Architect
|
||||
- Implementer
|
||||
- Researcher
|
||||
- Reviewer
|
||||
- Verifier
|
||||
|
||||
Agent use is proportional to the task. Small changes can stay with the implementer, while additional roles are available
|
||||
when research, design, independent review, or focused verification adds value.
|
||||
|
||||
## Extending the Configuration
|
||||
|
||||
### Add a rule
|
||||
|
||||
Create a focused Markdown file in `shared/rules/`. Add its loading condition to `shared/global-instructions.md` when the
|
||||
rule applies only to a language, framework, tool, or change area.
|
||||
|
||||
### Add a skill
|
||||
|
||||
Create `shared/skills/<category>/<skill>/SKILL.md` with valid YAML frontmatter and a concise workflow. Reference shared
|
||||
rules instead of repeating persistent standards.
|
||||
|
||||
### Add an agent
|
||||
|
||||
Create `shared/agents/<agent>/agent.yml` and `instructions.md`. Keep semantic behavior in these shared files; the build
|
||||
renders the Codex and Claude Code formats.
|
||||
|
||||
Rebuild after every semantic change.
|
||||
|
||||
## Security
|
||||
|
||||
- Never store API keys, OAuth tokens, credentials, authentication state, or sensitive logs in this repository.
|
||||
- Review generated output and use the installer's dry-run before installation.
|
||||
- Global installation happens only through an explicit installer invocation.
|
||||
- Plugins execute with permissions granted by their client; review their upstream sources and trust prompts.
|
||||
- Codex keeps workspace sandboxing enabled and requires escalation outside expected development boundaries.
|
||||
|
||||
## Support
|
||||
|
||||
Create an [issue](https://git.lechner-systems.at/fraujulian/MyAiConfiguration/issues) for problems or proposed changes.
|
||||
|
||||
## Contributors
|
||||
|
||||
~ [**FrauJulian - Julian Lechner**](https://fraujulian.xyz/)
|
||||
|
||||
## License
|
||||
|
||||
Licensed under the [MIT License](LICENSE).
|
||||
@@ -0,0 +1,3 @@
|
||||
# Claude Code adapter
|
||||
|
||||
Claude Code uses global `CLAUDE.md`, `settings.json`, skills, and agents under the user profile. This adapter supplies client metadata; semantic content remains in `shared/`.
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"permissions": {
|
||||
"defaultMode": "auto",
|
||||
"allow": [
|
||||
"Agent"
|
||||
],
|
||||
"deny": [
|
||||
"Bash(git reset --hard*)",
|
||||
"Bash(git clean*)",
|
||||
"Bash(rm -rf*)",
|
||||
"Bash(Remove-Item -Recurse*)"
|
||||
]
|
||||
},
|
||||
"env": {
|
||||
"CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY": "5"
|
||||
},
|
||||
"statusLine": {
|
||||
"type": "command",
|
||||
"command": "__STATUSLINE_COMMAND__ \"__AI_CONFIG_ROOT__/statusline/__STATUSLINE_SCRIPT__\""
|
||||
},
|
||||
"hooks": {
|
||||
"Stop": [
|
||||
{
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "__HOOK_COMMAND__ \"__AI_CONFIG_ROOT__/hooks/__HOOK_SCRIPT__\"",
|
||||
"timeout": 20
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
name: {{name}}
|
||||
description: {{description}}
|
||||
---
|
||||
|
||||
{{instructions}}
|
||||
@@ -0,0 +1,3 @@
|
||||
# Codex adapter
|
||||
|
||||
Codex uses global `AGENTS.md`, `config.toml`, skills, and agent configuration under the user profile. This adapter supplies client metadata; semantic content remains in `shared/`.
|
||||
@@ -0,0 +1,20 @@
|
||||
approval_policy = "on-request"
|
||||
approvals_reviewer = "auto_review"
|
||||
sandbox_mode = "workspace-write"
|
||||
|
||||
[tui]
|
||||
status_line = ["model", "reasoning", "project-name", "git-branch", "context-window-size", "context-used", "used-tokens"]
|
||||
|
||||
[agents]
|
||||
enabled = true
|
||||
max_threads = 5
|
||||
|
||||
[features]
|
||||
hooks = true
|
||||
|
||||
[[hooks.Stop]]
|
||||
[[hooks.Stop.hooks]]
|
||||
type = "command"
|
||||
command = '__HOOK_COMMAND__ "__AI_CONFIG_ROOT__/hooks/__HOOK_SCRIPT__"'
|
||||
command_windows = '__WINDOWS_HOOK_COMMAND__ "__AI_CONFIG_ROOT__/hooks/__WINDOWS_HOOK_SCRIPT__"'
|
||||
timeout = 20
|
||||
@@ -0,0 +1,3 @@
|
||||
name = "{{name}}"
|
||||
description = "{{description}}"
|
||||
instructions = "{{instructions}}"
|
||||
@@ -0,0 +1,5 @@
|
||||
name claude_marketplace claude_plugin codex_marketplace codex_plugin
|
||||
Ponytail DietrichGebert/ponytail ponytail@ponytail DietrichGebert/ponytail ponytail@ponytail
|
||||
i-have-adhd ayghri/i-have-adhd i-have-adhd@i-have-adhd ayghri/i-have-adhd i-have-adhd@i-have-adhd
|
||||
Superpowers - superpowers@claude-plugins-official openai-curated-remote superpowers@openai-curated-remote
|
||||
Context7 upstash/context7 context7@context7-marketplace upstash/context7 context7@context7-marketplace
|
||||
|
@@ -0,0 +1,11 @@
|
||||
# Agents
|
||||
|
||||
The five shared agents are logical roles, not mandatory steps.
|
||||
|
||||
- `implementer` executes the smallest complete engineering change and performs self-review.
|
||||
- `researcher` investigates code, patterns, evidence, alternatives, and unknowns without modifying implementation code by default.
|
||||
- `architect` evaluates technical boundaries, dependencies, interfaces, constraints, and design options.
|
||||
- `verifier` checks completed work against requested behavior, acceptance criteria, tests, generated output, and configuration.
|
||||
- `reviewer` independently checks correctness, regressions, security, maintainability, architecture, tests, and unnecessary complexity.
|
||||
|
||||
Use only the roles that are likely to improve the outcome. Choose `researcher`, `reviewer`, and `verifier` based on the task's uncertainty, complexity, risk, blast radius, and verification value; none runs automatically. The agent may make evidence-based, reversible technical decisions. Ask the user when technical choices remain materially uncertain or when business behavior, user-visible behavior, UI, UX, APIs, database models, configuration formats, compatibility behavior, or other high-impact decisions are ambiguous or open to interpretation.
|
||||
@@ -0,0 +1,5 @@
|
||||
# Architecture
|
||||
|
||||
Shared Markdown and metadata define meaning once. Codex and Claude adapters contain only client-specific paths, filenames, and serialization details. The build script renders those inputs into `generated/`. Installation is a separate, explicit step that copies generated files into global user-level locations with backups.
|
||||
|
||||
Generated output is ignored because it is reproducible build output. The source files are the reviewable record.
|
||||
@@ -0,0 +1,9 @@
|
||||
# Configuration
|
||||
|
||||
Codex receives a generated global `AGENTS.md`, agent TOML files, skills, and a `config.toml` adapter with workspace sandboxing, interactive approval boundaries, automatic approval review, enabled sub-agents, and a five-thread concurrency limit. Claude Code receives a generated global `CLAUDE.md`, agent Markdown files, skills, and `settings.json` with the `auto` permission mode, explicit `Agent` permission, and a five-operation tool/sub-agent concurrency limit. The exact installed locations are resolved from the user profile at install time; no machine-specific absolute path is stored in the repository.
|
||||
|
||||
Neither current client configuration model exposes a supported global `max_depth` setting. The repository does not emit an unsupported key that would be ignored or cause configuration validation errors.
|
||||
|
||||
Client settings remain thin adapters. Shared semantics remain in `shared/`.
|
||||
|
||||
User plugins are managed separately through `adapters/plugins.tsv` and the client-native plugin commands. They are not copied into `generated/` because each client owns its plugin cache and authentication state.
|
||||
@@ -0,0 +1,7 @@
|
||||
# Hooks
|
||||
|
||||
Deterministic safety and validation hooks live in `shared/hooks/scripts/`. The flashbang entry points live directly in `shared/hooks/`. The command safety hook rejects obvious destructive commands outside the current development workspace. The session validation hook checks repository-local generated inputs. The post-change hook is an optional verification entry point.
|
||||
|
||||
The build includes the hooks and their client-specific registration in each payload. Installation places them beside the generated client files. The scripts do not grant permissions, bypass approvals, or replace client permission systems.
|
||||
|
||||
The PowerShell and Bash hook variants are registered only for the Codex and Claude `Stop` events. They run after the main agent finishes responding, not during tool calls, thinking, permission requests, or notifications. The default flash lasts about 500 milliseconds. The Windows command deliberately omits `-WindowStyle Hidden`, which can hide or minimize the shared terminal. The PowerShell hook creates a low-opacity click-through overlay without activating another window. The Bash hook creates the equivalent temporary overlay through Python's standard `tkinter` module, uses `xrandr` for multi-monitor bounds when available, and does not reactivate the terminal. It falls back to `notify-send` in headless or minimal environments. Hooks are intentionally not executed during build or doctor.
|
||||
@@ -0,0 +1,11 @@
|
||||
# Plugins
|
||||
|
||||
The user-level plugin manifest is `adapters/plugins.tsv`. It maps each logical plugin to the marketplace selector understood by Claude Code and Codex.
|
||||
|
||||
The current baseline includes Ponytail, i-have-adhd, Superpowers, and Context7. The install script operates at user scope and is idempotent: existing Claude plugins are enabled and updated, and Codex plugins are updated or ensured through the Codex plugin command.
|
||||
|
||||
Plugin installation requires the corresponding client CLI, network access, and any authentication required by the plugin. Context7 may open an OAuth flow. Codex or plugin hooks may require a trust review in `/hooks`. The scripts never install plugins during a build or doctor run and never install them when `--dry-run` or `-DryRun` is used.
|
||||
|
||||
If Codex reports that a marketplace is already registered from another source, the scripts remove only the conflicting marketplace name from the configured user-level Codex sources, add the repository source from the manifest, and continue with the Codex plugin command. Other marketplace errors remain fatal.
|
||||
|
||||
Only trusted upstream marketplace sources should be added. Plugins are executable extensions and may access the permissions granted to their client.
|
||||
@@ -0,0 +1,15 @@
|
||||
# Skills
|
||||
|
||||
Skills are reusable workflows. Rules are persistent constraints and agents are specialized roles. Each skill is a minimal `SKILL.md` with YAML frontmatter and a small initial workflow so both clients can consume it.
|
||||
|
||||
The current structure is organized by purpose:
|
||||
|
||||
- `debugging/`
|
||||
- `planning/`: implementation planning, impact analysis, and work-item definition
|
||||
- `research/`: technical and repository research
|
||||
- `reviews/`: code, security, performance, WPF, UI/UX, business, API, and EF Core reviews
|
||||
- `implementation/`: SQL, unit-test, and integration-test writing
|
||||
- `verification/`: facts, work-item, and regression verification
|
||||
- `git/`: pull request responses and reviews
|
||||
|
||||
The files intentionally define only a small baseline. Detailed personal workflows and standards can be added later without changing the structure.
|
||||
@@ -0,0 +1,78 @@
|
||||
[CmdletBinding()]
|
||||
param()
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$root = Split-Path $PSScriptRoot -Parent
|
||||
$shared = Join-Path $root 'shared'
|
||||
$output = Join-Path $root 'generated'
|
||||
$pluginManifest = Join-Path $root 'adapters/plugins.tsv'
|
||||
if (-not (Test-Path -LiteralPath $pluginManifest)) { throw "Missing plugin manifest: $pluginManifest" }
|
||||
$pluginEntries = @(Import-Csv -LiteralPath $pluginManifest -Delimiter ([char]9))
|
||||
if ($pluginEntries.Count -ne 4) { throw 'Plugin manifest must define exactly four plugins.' }
|
||||
foreach ($pluginEntry in $pluginEntries) {
|
||||
foreach ($field in @('claude_plugin','codex_plugin')) {
|
||||
if ([string]::IsNullOrWhiteSpace($pluginEntry.$field)) { throw "Missing $field for plugin $($pluginEntry.name)." }
|
||||
}
|
||||
}
|
||||
Remove-Item $output -Recurse -Force -ErrorAction SilentlyContinue
|
||||
New-Item $output -ItemType Directory -Force | Out-Null
|
||||
function Copy-Directory($source, $destination) {
|
||||
New-Item $destination -ItemType Directory -Force | Out-Null
|
||||
Get-ChildItem $source -File -Recurse | ForEach-Object {
|
||||
$relative = $_.FullName.Substring($source.Length).TrimStart([char[]]@('\','/'))
|
||||
$target = Join-Path $destination $relative
|
||||
New-Item (Split-Path $target -Parent) -ItemType Directory -Force | Out-Null
|
||||
Copy-Item $_.FullName $target -Force
|
||||
}
|
||||
}
|
||||
function Read-Field($path, $name) {
|
||||
$line = Get-Content $path | Where-Object { $_ -match ('^' + [regex]::Escape($name) + ':\s*(.*)$') } | Select-Object -First 1
|
||||
if (-not $line) { throw "Missing $name in $path" }
|
||||
return ([regex]::Match($line, '^' + [regex]::Escape($name) + ':\s*(.*)$')).Groups[1].Value.Trim()
|
||||
}
|
||||
function Quote-Toml($value) {
|
||||
return ('"' + $value.Replace('\','\\').Replace('"','\"').Replace("`r",'').Replace("`n",'\n') + '"')
|
||||
}
|
||||
& (Join-Path $root 'shared/hooks/scripts/Test-SessionConfig.ps1') -RepositoryRoot $root
|
||||
foreach ($platform in @('windows','linux')) {
|
||||
Copy-Directory (Join-Path $shared 'skills') (Join-Path $output "codex-$platform/skills")
|
||||
Copy-Directory (Join-Path $shared 'skills') (Join-Path $output "claude-$platform/skills")
|
||||
Copy-Directory (Join-Path $shared 'rules') (Join-Path $output "codex-$platform/rules")
|
||||
Copy-Directory (Join-Path $shared 'rules') (Join-Path $output "claude-$platform/rules")
|
||||
New-Item (Join-Path $output "codex-$platform") -ItemType Directory -Force | Out-Null
|
||||
New-Item (Join-Path $output "claude-$platform") -ItemType Directory -Force | Out-Null
|
||||
Copy-Directory (Join-Path $shared 'hooks') (Join-Path $output "codex-$platform/hooks")
|
||||
Copy-Directory (Join-Path $shared 'hooks') (Join-Path $output "claude-$platform/hooks")
|
||||
Copy-Directory (Join-Path $shared 'statusline') (Join-Path $output "claude-$platform/statusline")
|
||||
Copy-Item (Join-Path $shared 'global-instructions.md') (Join-Path $output "codex-$platform/AGENTS.md") -Force
|
||||
Copy-Item (Join-Path $shared 'global-instructions.md') (Join-Path $output "claude-$platform/CLAUDE.md") -Force
|
||||
Copy-Item (Join-Path $root 'adapters/codex/config/config.toml') (Join-Path $output "codex-$platform/config.toml") -Force
|
||||
Copy-Item (Join-Path $root 'adapters/claude/config/settings.json') (Join-Path $output "claude-$platform/settings.json") -Force
|
||||
foreach ($client in @('codex','claude')) {
|
||||
$agentsOutput = Join-Path $output "$client-$platform/agents"
|
||||
New-Item $agentsOutput -ItemType Directory -Force | Out-Null
|
||||
Get-ChildItem (Join-Path $shared 'agents') -Directory | Sort-Object Name | ForEach-Object {
|
||||
$metadata = Join-Path $_.FullName 'agent.yml'
|
||||
$name = Read-Field $metadata 'name'
|
||||
$description = Read-Field $metadata 'description'
|
||||
$instructions = Get-Content (Join-Path $_.FullName 'instructions.md') -Raw
|
||||
if ($client -eq 'codex') {
|
||||
Set-Content (Join-Path $agentsOutput "$name.toml") "name = $(Quote-Toml $name)`r`ndescription = $(Quote-Toml $description)`r`ndeveloper_instructions = $(Quote-Toml $instructions)" -Encoding UTF8
|
||||
} else {
|
||||
Set-Content (Join-Path $agentsOutput "$name.md") "---`r`nname: $name`r`ndescription: $description`r`n---`r`n`r`n$instructions" -Encoding UTF8
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($client in @('codex','claude')) {
|
||||
$file = if ($client -eq 'codex') { 'config.toml' } else { 'settings.json' }
|
||||
$path = Join-Path $output "$client-$platform/$file"
|
||||
$command = if ($platform -eq 'windows') { 'powershell -NoProfile -ExecutionPolicy Bypass -File' } else { 'bash' }
|
||||
$script = if ($platform -eq 'windows') { 'flashbang.ps1' } else { 'flashbang.sh' }
|
||||
$statusLineScript = if ($platform -eq 'windows') { 'statusline.ps1' } else { 'statusline.sh' }
|
||||
$content = Get-Content -LiteralPath $path -Raw
|
||||
$content = $content.Replace('__HOOK_COMMAND__', $command).Replace('__WINDOWS_HOOK_COMMAND__', $command).Replace('__HOOK_SCRIPT__', $script).Replace('__WINDOWS_HOOK_SCRIPT__', $script).Replace('__STATUSLINE_COMMAND__', $command).Replace('__STATUSLINE_SCRIPT__', $statusLineScript)
|
||||
Set-Content -LiteralPath $path -Value $content -Encoding UTF8
|
||||
}
|
||||
}
|
||||
Write-Output 'PASS build: codex-windows, claude-windows, codex-linux, claude-linux'
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
root=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)
|
||||
shared="$root/shared"
|
||||
output="$root/generated"
|
||||
plugin_manifest="$root/adapters/plugins.tsv"
|
||||
[ -f "$plugin_manifest" ] || { printf 'Missing plugin manifest: %s\n' "$plugin_manifest" >&2; exit 1; }
|
||||
[ "$(awk 'NR > 1 && NF == 5 { count++ } END { print count + 0 }' "$plugin_manifest")" -eq 4 ] || { printf 'Plugin manifest must define exactly four plugins.\n' >&2; exit 1; }
|
||||
|
||||
copy_directory() {
|
||||
local source=$1 destination=$2
|
||||
mkdir -p "$destination"
|
||||
cp -R "$source"/. "$destination"/
|
||||
}
|
||||
|
||||
read_field() {
|
||||
local path=$1 name=$2 value
|
||||
value=$(sed -n "s/^${name}:[[:space:]]*//p" "$path" | head -n 1)
|
||||
[ -n "$value" ] || { printf 'Missing %s in %s\n' "$name" "$path" >&2; exit 1; }
|
||||
printf '%s' "$value"
|
||||
}
|
||||
|
||||
quote_toml() {
|
||||
local value=$1
|
||||
value=${value//\\/\\\\}
|
||||
value=${value//\"/\\\"}
|
||||
value=${value//$'\r'/}
|
||||
value=${value//$'\n'/\\n}
|
||||
printf '"%s"' "$value"
|
||||
}
|
||||
|
||||
bash "$shared/hooks/scripts/test-session-config.sh" "$root"
|
||||
rm -rf -- "$output"
|
||||
for platform in windows linux; do
|
||||
mkdir -p "$output/codex-$platform" "$output/claude-$platform"
|
||||
copy_directory "$shared/skills" "$output/codex-$platform/skills"
|
||||
copy_directory "$shared/skills" "$output/claude-$platform/skills"
|
||||
copy_directory "$shared/rules" "$output/codex-$platform/rules"
|
||||
copy_directory "$shared/rules" "$output/claude-$platform/rules"
|
||||
copy_directory "$shared/hooks" "$output/codex-$platform/hooks"
|
||||
copy_directory "$shared/hooks" "$output/claude-$platform/hooks"
|
||||
copy_directory "$shared/statusline" "$output/claude-$platform/statusline"
|
||||
|
||||
cp "$shared/global-instructions.md" "$output/codex-$platform/AGENTS.md"
|
||||
cp "$shared/global-instructions.md" "$output/claude-$platform/CLAUDE.md"
|
||||
cp "$root/adapters/codex/config/config.toml" "$output/codex-$platform/config.toml"
|
||||
cp "$root/adapters/claude/config/settings.json" "$output/claude-$platform/settings.json"
|
||||
|
||||
for client in codex claude; do
|
||||
agents_output="$output/$client-$platform/agents"
|
||||
mkdir -p "$agents_output"
|
||||
for agent in "$shared"/agents/*; do
|
||||
metadata="$agent/agent.yml"
|
||||
name=$(read_field "$metadata" name)
|
||||
description=$(read_field "$metadata" description)
|
||||
instructions=$(<"$agent/instructions.md")
|
||||
if [ "$client" = codex ]; then
|
||||
printf 'name = %s\ndescription = %s\ndeveloper_instructions = %s\n' "$(quote_toml "$name")" "$(quote_toml "$description")" "$(quote_toml "$instructions")" > "$agents_output/$name.toml"
|
||||
else
|
||||
printf '%s\nname: %s\ndescription: %s\n%s\n\n%s\n' '---' "$name" "$description" '---' "$instructions" > "$agents_output/$name.md"
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
for client in codex claude; do
|
||||
file=config.toml
|
||||
[ "$client" != claude ] || file=settings.json
|
||||
command=bash
|
||||
script=flashbang.sh
|
||||
statusline_script=statusline.sh
|
||||
if [ "$platform" = windows ]; then
|
||||
command='powershell -NoProfile -ExecutionPolicy Bypass -File'
|
||||
script=flashbang.ps1
|
||||
statusline_script=statusline.ps1
|
||||
fi
|
||||
path="$output/$client-$platform/$file"
|
||||
content=$(<"$path")
|
||||
content=${content//__HOOK_COMMAND__/$command}
|
||||
content=${content//__WINDOWS_HOOK_COMMAND__/$command}
|
||||
content=${content//__HOOK_SCRIPT__/$script}
|
||||
content=${content//__WINDOWS_HOOK_SCRIPT__/$script}
|
||||
content=${content//__STATUSLINE_COMMAND__/$command}
|
||||
content=${content//__STATUSLINE_SCRIPT__/$statusline_script}
|
||||
printf '%s\n' "$content" > "$path"
|
||||
done
|
||||
done
|
||||
printf 'PASS build: codex-windows, claude-windows, codex-linux, claude-linux\n'
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
[CmdletBinding()]
|
||||
param()
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$root = Split-Path $PSScriptRoot -Parent
|
||||
$homePath = [Environment]::GetFolderPath('UserProfile')
|
||||
$fail = $false
|
||||
function Result($state, $message) { Write-Output ("$state $message"); if ($state -eq 'FAIL') { $script:fail = $true } }
|
||||
foreach ($tool in @('codex','claude')) { if (Get-Command $tool -ErrorAction SilentlyContinue) { $version = & $tool --version 2>&1 | Select-Object -First 1; Result 'PASS' "$tool available ($version)" } else { Result 'WARN' "$tool unavailable" } }
|
||||
if ($PSVersionTable.PSVersion.Major -ge 6 -and -not $IsWindows) { if (Get-Command jq -ErrorAction SilentlyContinue) { Result 'PASS' 'jq available for Claude status line' } else { Result 'WARN' 'jq unavailable; Claude status line is disabled' } }
|
||||
foreach ($platform in @('windows','linux')) {
|
||||
if (Test-Path (Join-Path $root "generated/codex-$platform/AGENTS.md")) { Result 'PASS' 'generated output present' } else { Result 'FAIL' 'generated output missing; run build' }
|
||||
if ((Test-Path (Join-Path $root "generated/codex-$platform/hooks/scripts/Validate-CommandSafety.ps1")) -and (Test-Path (Join-Path $root "generated/codex-$platform/hooks/scripts/validate-command-safety.sh")) -and (Test-Path (Join-Path $root "generated/claude-$platform/hooks/scripts/Validate-CommandSafety.ps1")) -and (Test-Path (Join-Path $root "generated/claude-$platform/hooks/scripts/validate-command-safety.sh"))) { Result 'PASS' 'generated hooks present' } else { Result 'FAIL' 'generated hooks missing; run build' }
|
||||
}
|
||||
foreach ($path in @('.codex/AGENTS.md','.codex/config.toml','.claude/CLAUDE.md','.claude/settings.json')) { if (Test-Path (Join-Path $homePath $path)) { Result 'PASS' "installed $path" } else { Result 'WARN' "not installed $path" } }
|
||||
foreach ($path in @('shared/rules','shared/skills','shared/agents','shared/hooks/scripts')) { if (Test-Path (Join-Path $root $path)) { Result 'PASS' "source $path" } else { Result 'FAIL' "missing $path" } }
|
||||
if ($fail) { exit 1 }
|
||||
Write-Output 'PASS doctor'
|
||||
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
root=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)
|
||||
home_path=${HOME:?HOME is required}
|
||||
failed=false
|
||||
|
||||
result() {
|
||||
printf '%s %s\n' "$1" "$2"
|
||||
[ "$1" != FAIL ] || failed=true
|
||||
}
|
||||
|
||||
for tool in codex claude; do
|
||||
if command -v "$tool" >/dev/null; then result PASS "$tool available ($($tool --version 2>&1 | head -n 1))"; else result WARN "$tool unavailable"; fi
|
||||
done
|
||||
command -v jq >/dev/null && result PASS 'jq available for Claude status line' || result WARN 'jq unavailable; Claude status line is disabled'
|
||||
for platform in windows linux; do
|
||||
[ -f "$root/generated/codex-$platform/AGENTS.md" ] && result PASS 'generated output present' || result FAIL 'generated output missing; run build'
|
||||
[ -f "$root/generated/codex-$platform/hooks/scripts/Validate-CommandSafety.ps1" ] && [ -f "$root/generated/codex-$platform/hooks/scripts/validate-command-safety.sh" ] && [ -f "$root/generated/claude-$platform/hooks/scripts/Validate-CommandSafety.ps1" ] && [ -f "$root/generated/claude-$platform/hooks/scripts/validate-command-safety.sh" ] && result PASS 'generated hooks present' || result FAIL 'generated hooks missing; run build'
|
||||
done
|
||||
for path in .codex/AGENTS.md .codex/config.toml .claude/CLAUDE.md .claude/settings.json; do
|
||||
[ -f "$home_path/$path" ] && result PASS "installed $path" || result WARN "not installed $path"
|
||||
done
|
||||
for path in shared/rules shared/skills shared/agents shared/hooks/scripts; do
|
||||
[ -e "$root/$path" ] && result PASS "source $path" || result FAIL "missing $path"
|
||||
done
|
||||
"$failed" && exit 1
|
||||
printf 'PASS doctor\n'
|
||||
@@ -0,0 +1,58 @@
|
||||
[CmdletBinding()]
|
||||
param([switch]$DryRun)
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$root = Split-Path $PSScriptRoot -Parent
|
||||
. (Join-Path $PSScriptRoot 'lib/plugins.ps1')
|
||||
$buildScript = Join-Path $PSScriptRoot 'build.ps1'
|
||||
& $buildScript
|
||||
if (-not $?) { throw 'Build failed. Installation was not started.' }
|
||||
$generated = Join-Path $root 'generated'
|
||||
if (-not (Test-Path $generated)) { throw 'Generated output is missing after a successful build.' }
|
||||
Write-Output 'Select target platform:'
|
||||
Write-Output '1) Windows'
|
||||
Write-Output '2) Linux'
|
||||
do { $platformSelection = Read-Host 'Selection [1-2]' } while ($platformSelection -notin @('1','2'))
|
||||
$platform = @{'1'='windows'; '2'='linux'}[$platformSelection]
|
||||
Write-Output 'Select installation target:'
|
||||
Write-Output '1) Codex'
|
||||
Write-Output '2) Claude'
|
||||
Write-Output '3) Both'
|
||||
do { $selection = Read-Host 'Selection [1-3]' } while ($selection -notin @('1','2','3'))
|
||||
$Client = @{'1'='Codex'; '2'='Claude'; '3'='Both'}[$selection]
|
||||
$stamp = Get-Date -Format 'yyyyMMdd-HHmmss'
|
||||
$homePath = [Environment]::GetFolderPath('UserProfile')
|
||||
$shellCommand = 'pwsh -NoProfile -ExecutionPolicy Bypass -File'
|
||||
$windowsShellCommand = 'powershell -NoProfile -ExecutionPolicy Bypass -File'
|
||||
if ([Environment]::OSVersion.Platform -eq [PlatformID]::Win32NT) { $shellCommand = $windowsShellCommand }
|
||||
$targets = @()
|
||||
if ($Client -in @('Codex','Both')) { $targets += @{ Source=(Join-Path $generated "codex-$platform"); Destination=(Join-Path $homePath '.codex') } }
|
||||
if ($Client -in @('Codex','Both')) { $targets += @{ Source=(Join-Path $generated "codex-$platform/skills"); Destination=(Join-Path $homePath '.agents/skills') } }
|
||||
if ($Client -in @('Claude','Both')) { $targets += @{ Source=(Join-Path $generated "claude-$platform"); Destination=(Join-Path $homePath '.claude') } }
|
||||
foreach ($item in $targets) {
|
||||
$backupRoot = Join-Path $item.Destination 'backups'
|
||||
Get-ChildItem $item.Source -File -Recurse | ForEach-Object {
|
||||
$relative = $_.FullName.Substring($item.Source.Length).TrimStart([char[]]@('\','/'))
|
||||
$target = Join-Path $item.Destination $relative
|
||||
if ($DryRun) { Write-Output "DRYRUN $($_.FullName) -> $target"; return }
|
||||
if (Test-Path $target) {
|
||||
$backup = Join-Path $backupRoot $relative
|
||||
New-Item (Split-Path $backup -Parent) -ItemType Directory -Force | Out-Null
|
||||
Copy-Item $target "$backup.$stamp" -Force
|
||||
}
|
||||
New-Item (Split-Path $target -Parent) -ItemType Directory -Force | Out-Null
|
||||
$content = Get-Content $_.FullName -Raw
|
||||
if ($content.Contains('__AI_CONFIG_ROOT__') -or $content.Contains('__HOOK_COMMAND__') -or $content.Contains('__WINDOWS_HOOK_COMMAND__')) {
|
||||
$replacement = $item.Destination.Replace('\','/')
|
||||
$content = $content.Replace('__AI_CONFIG_ROOT__', $replacement)
|
||||
$content = $content.Replace('__HOOK_COMMAND__', $shellCommand)
|
||||
$content = $content.Replace('__WINDOWS_HOOK_COMMAND__', $windowsShellCommand)
|
||||
$content = $content.Replace('__HOOK_SCRIPT__', 'flashbang.ps1')
|
||||
$content = $content.Replace('__WINDOWS_HOOK_SCRIPT__', 'flashbang.ps1')
|
||||
[System.IO.File]::WriteAllText($target, $content, (New-Object System.Text.UTF8Encoding($false)))
|
||||
}
|
||||
else { Copy-Item $_.FullName $target -Force }
|
||||
Write-Output "INSTALL $target"
|
||||
}
|
||||
}
|
||||
Install-ConfiguredPlugins -RepositoryRoot $root -Client $Client -DryRun:$DryRun -Update
|
||||
Write-Output ($(if ($DryRun) { 'PASS install dry-run' } else { 'PASS install' }))
|
||||
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
dry_run=false
|
||||
for argument in "$@"; do
|
||||
[ "$argument" != "--dry-run" ] || dry_run=true
|
||||
done
|
||||
root=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)
|
||||
. "$root/scripts/lib/plugins.sh"
|
||||
bash "$root/scripts/build.sh"
|
||||
generated="$root/generated"
|
||||
[ -d "$generated" ] || { printf 'Generated output is missing after a successful build.\n' >&2; exit 1; }
|
||||
|
||||
printf 'Select target platform:\n1) Windows\n2) Linux\n'
|
||||
while :; do
|
||||
read -r -p 'Selection [1-2] ' platform_selection
|
||||
case "$platform_selection" in 1) platform=windows; break;; 2) platform=linux; break;; esac
|
||||
done
|
||||
printf 'Select installation target:\n1) Codex\n2) Claude\n3) Both\n'
|
||||
while :; do
|
||||
read -r -p 'Selection [1-3] ' selection
|
||||
case "$selection" in 1|2|3) break;; esac
|
||||
done
|
||||
|
||||
stamp=$(date +%Y%m%d-%H%M%S)
|
||||
home_path=${HOME:?HOME is required}
|
||||
targets=()
|
||||
case "$selection" in
|
||||
1|3) targets+=("$generated/codex-$platform|$home_path/.codex" "$generated/codex-$platform/skills|$home_path/.agents/skills");;
|
||||
esac
|
||||
case "$selection" in
|
||||
2|3) targets+=("$generated/claude-$platform|$home_path/.claude");;
|
||||
esac
|
||||
|
||||
for target_pair in "${targets[@]}"; do
|
||||
source=${target_pair%%|*}
|
||||
destination=${target_pair#*|}
|
||||
while IFS= read -r -d '' source_file; do
|
||||
relative=${source_file#"$source/"}
|
||||
target="$destination/$relative"
|
||||
if "$dry_run"; then printf 'DRYRUN %s -> %s\n' "$source_file" "$target"; continue; fi
|
||||
if [ -f "$target" ]; then
|
||||
backup="$destination/backups/$relative.$stamp"
|
||||
mkdir -p "$(dirname -- "$backup")"
|
||||
cp "$target" "$backup"
|
||||
fi
|
||||
mkdir -p "$(dirname -- "$target")"
|
||||
content=$(<"$source_file")
|
||||
if [[ "$content" == *'__AI_CONFIG_ROOT__'* || "$content" == *'__HOOK_COMMAND__'* || "$content" == *'__WINDOWS_HOOK_COMMAND__'* ]]; then
|
||||
replacement=$destination
|
||||
if command -v cygpath >/dev/null; then replacement=$(cygpath -m "$destination"); fi
|
||||
content=${content//__AI_CONFIG_ROOT__/$replacement}
|
||||
content=${content//__HOOK_COMMAND__/bash}
|
||||
content=${content//__WINDOWS_HOOK_COMMAND__/bash}
|
||||
content=${content//__HOOK_SCRIPT__/flashbang.sh}
|
||||
content=${content//__WINDOWS_HOOK_SCRIPT__/flashbang.sh}
|
||||
printf '%s' "$content" > "$target"
|
||||
else
|
||||
cp "$source_file" "$target"
|
||||
fi
|
||||
printf 'INSTALL %s\n' "$target"
|
||||
done < <(find "$source" -type f -print0)
|
||||
done
|
||||
|
||||
client_selection=both
|
||||
case "$selection" in
|
||||
1) client_selection=codex;;
|
||||
2) client_selection=claude;;
|
||||
esac
|
||||
install_configured_plugins "$root" "$client_selection" "$dry_run" true
|
||||
|
||||
if "$dry_run"; then printf 'PASS install dry-run\n'; else printf 'PASS install\n'; fi
|
||||
@@ -0,0 +1,119 @@
|
||||
function Invoke-PluginCommand {
|
||||
param(
|
||||
[Parameter(Mandatory=$true)][string]$Command,
|
||||
[Parameter(Mandatory=$true)][string[]]$Arguments,
|
||||
[switch]$DryRun
|
||||
)
|
||||
$display = "$Command $($Arguments -join ' ')"
|
||||
if ($DryRun) { Write-Output "DRYRUN $display"; return }
|
||||
& $Command @Arguments
|
||||
if ($LASTEXITCODE -ne 0) { throw "Plugin command failed: $display" }
|
||||
}
|
||||
|
||||
function Get-ConfiguredPluginEntries {
|
||||
param([Parameter(Mandatory=$true)][string]$RepositoryRoot)
|
||||
$manifest = Join-Path $RepositoryRoot 'adapters/plugins.tsv'
|
||||
if (-not (Test-Path -LiteralPath $manifest)) { throw "Plugin manifest is missing: $manifest" }
|
||||
Import-Csv -LiteralPath $manifest -Delimiter ([char]9) | ForEach-Object {
|
||||
$_.claude_plugin = $_.claude_plugin.Trim()
|
||||
$_.codex_plugin = $_.codex_plugin.Trim()
|
||||
$_
|
||||
}
|
||||
}
|
||||
|
||||
function Get-InstalledPlugins {
|
||||
param([ValidateSet('Claude','Codex')][string]$Client)
|
||||
if ($Client -eq 'Claude') {
|
||||
if (-not (Get-Command claude -ErrorAction SilentlyContinue)) { throw 'Claude Code CLI is required to manage Claude plugins.' }
|
||||
$items = (claude plugin list --json | Out-String) | ConvertFrom-Json
|
||||
return @($items)
|
||||
}
|
||||
if (-not (Get-Command codex -ErrorAction SilentlyContinue)) { throw 'Codex CLI is required to manage Codex plugins.' }
|
||||
$items = (codex plugin list --json | Out-String) | ConvertFrom-Json
|
||||
return @($items.installed)
|
||||
}
|
||||
|
||||
function Ensure-CodexMarketplace {
|
||||
param(
|
||||
[Parameter(Mandatory=$true)][string]$Source,
|
||||
[Parameter(Mandatory=$true)][string]$MarketplaceName,
|
||||
[switch]$DryRun
|
||||
)
|
||||
if ($DryRun) {
|
||||
Write-Output "DRYRUN codex plugin marketplace add $Source"
|
||||
return
|
||||
}
|
||||
$previousErrorActionPreference = $ErrorActionPreference
|
||||
try {
|
||||
$ErrorActionPreference = 'Continue'
|
||||
$output = @(& codex plugin marketplace add $Source 2>&1)
|
||||
$exitCode = $LASTEXITCODE
|
||||
} catch {
|
||||
$output = @($_)
|
||||
$exitCode = 1
|
||||
} finally {
|
||||
$ErrorActionPreference = $previousErrorActionPreference
|
||||
}
|
||||
$output | ForEach-Object { Write-Output $_ }
|
||||
if ($exitCode -eq 0) { return }
|
||||
|
||||
$text = $output -join [Environment]::NewLine
|
||||
if ($text -match 'marketplace .* already added from a different source') {
|
||||
Write-Output "WARN Codex marketplace '$MarketplaceName' exists from another source; replacing it with: $Source"
|
||||
Invoke-PluginCommand -Command 'codex' -Arguments @('plugin','marketplace','remove',$MarketplaceName)
|
||||
Invoke-PluginCommand -Command 'codex' -Arguments @('plugin','marketplace','add',$Source)
|
||||
return
|
||||
}
|
||||
throw "Plugin command failed: codex plugin marketplace add $Source"
|
||||
}
|
||||
|
||||
function Install-ConfiguredPlugins {
|
||||
param(
|
||||
[Parameter(Mandatory=$true)][string]$RepositoryRoot,
|
||||
[ValidateSet('Codex','Claude','Both')][Parameter(Mandatory=$true)][string]$Client,
|
||||
[switch]$DryRun,
|
||||
[switch]$Update
|
||||
)
|
||||
$entries = @(Get-ConfiguredPluginEntries -RepositoryRoot $RepositoryRoot)
|
||||
$clients = if ($Client -eq 'Both') { @('Claude','Codex') } else { @($Client) }
|
||||
|
||||
foreach ($selectedClient in $clients) {
|
||||
$installed = if ($DryRun) { @() } else { @(Get-InstalledPlugins -Client $selectedClient) }
|
||||
foreach ($entry in $entries) {
|
||||
$marketplace = if ($selectedClient -eq 'Claude') { $entry.claude_marketplace.Trim() } else { $entry.codex_marketplace.Trim() }
|
||||
if ($marketplace -eq '-') { $marketplace = '' }
|
||||
$plugin = if ($selectedClient -eq 'Claude') { $entry.claude_plugin } else { $entry.codex_plugin }
|
||||
if ([string]::IsNullOrWhiteSpace($plugin)) { throw ('Plugin selector missing for {0}: {1}' -f $selectedClient, $entry.name) }
|
||||
|
||||
$installedItem = if ($selectedClient -eq 'Claude') { $installed | Where-Object { $_.id -eq $plugin } | Select-Object -First 1 } else { $installed | Where-Object { $_.pluginId -eq $plugin } | Select-Object -First 1 }
|
||||
if ($Update -and $selectedClient -eq 'Claude' -and $null -ne $installedItem) {
|
||||
Invoke-PluginCommand -Command 'claude' -Arguments @('plugin','update',$plugin) -DryRun:$DryRun
|
||||
if (-not $installedItem.enabled) {
|
||||
Invoke-PluginCommand -Command 'claude' -Arguments @('plugin','enable',$plugin) -DryRun:$DryRun
|
||||
}
|
||||
continue
|
||||
}
|
||||
if (-not $Update -and $null -ne $installedItem) {
|
||||
if ($selectedClient -eq 'Claude' -and -not $installedItem.enabled) {
|
||||
Invoke-PluginCommand -Command 'claude' -Arguments @('plugin','enable',$plugin) -DryRun:$DryRun
|
||||
}
|
||||
Write-Output "PASS $selectedClient plugin already installed: $plugin"
|
||||
continue
|
||||
}
|
||||
|
||||
if ($selectedClient -eq 'Claude') {
|
||||
if (-not [string]::IsNullOrWhiteSpace($marketplace)) {
|
||||
Invoke-PluginCommand -Command 'claude' -Arguments @('plugin','marketplace','add',$marketplace) -DryRun:$DryRun
|
||||
}
|
||||
Invoke-PluginCommand -Command 'claude' -Arguments @('plugin','install',$plugin,'--scope','user') -DryRun:$DryRun
|
||||
} else {
|
||||
if (-not [string]::IsNullOrWhiteSpace($marketplace) -and $marketplace -ne 'openai-curated-remote') {
|
||||
$marketplaceName = ($plugin -split '@')[-1]
|
||||
Ensure-CodexMarketplace -Source $marketplace -MarketplaceName $marketplaceName -DryRun:$DryRun
|
||||
}
|
||||
Invoke-PluginCommand -Command 'codex' -Arguments @('plugin','add',$plugin) -DryRun:$DryRun
|
||||
}
|
||||
Write-Output "PASS $selectedClient plugin ensured: $plugin"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
plugin_installed() {
|
||||
local client=$1 plugin=$2
|
||||
if [ "$client" = claude ]; then
|
||||
claude plugin list --json 2>/dev/null | grep -Fq "\"id\": \"$plugin\""
|
||||
else
|
||||
codex plugin list --json 2>/dev/null | grep -Fq "\"pluginId\": \"$plugin\""
|
||||
fi
|
||||
}
|
||||
|
||||
run_plugin_command() {
|
||||
local dry_run=$1
|
||||
shift
|
||||
if [ "$dry_run" = true ]; then
|
||||
printf 'DRYRUN %s\n' "$*"
|
||||
else
|
||||
"$@"
|
||||
fi
|
||||
}
|
||||
|
||||
ensure_codex_marketplace() {
|
||||
local dry_run=$1 source=$2 marketplace_name=$3 output
|
||||
if [ "$dry_run" = true ]; then
|
||||
printf 'DRYRUN codex plugin marketplace add %s\n' "$source"
|
||||
return 0
|
||||
fi
|
||||
if output=$(codex plugin marketplace add "$source" 2>&1); then
|
||||
[ -z "$output" ] || printf '%s\n' "$output"
|
||||
return 0
|
||||
fi
|
||||
printf '%s\n' "$output" >&2
|
||||
if printf '%s\n' "$output" | grep -Eiq 'marketplace .* already added from a different source'; then
|
||||
printf "WARN Codex marketplace '%s' exists from another source; replacing it with: %s\n" "$marketplace_name" "$source"
|
||||
codex plugin marketplace remove "$marketplace_name"
|
||||
codex plugin marketplace add "$source"
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
install_configured_plugins() {
|
||||
local root=$1 client_selection=$2 dry_run=$3 update=$4
|
||||
local manifest="$root/adapters/plugins.tsv"
|
||||
[ -f "$manifest" ] || { printf 'Plugin manifest is missing: %s\n' "$manifest" >&2; return 1; }
|
||||
|
||||
local clients=()
|
||||
case "$client_selection" in
|
||||
codex) clients=(codex);;
|
||||
claude) clients=(claude);;
|
||||
both) clients=(claude codex);;
|
||||
*) printf 'Unknown plugin client selection: %s\n' "$client_selection" >&2; return 1;;
|
||||
esac
|
||||
|
||||
local client name claude_marketplace claude_plugin codex_marketplace codex_plugin marketplace plugin
|
||||
while IFS=$'\t' read -r name claude_marketplace claude_plugin codex_marketplace codex_plugin; do
|
||||
[ "$name" = name ] && continue
|
||||
[ -n "$name" ] || continue
|
||||
[ "$claude_marketplace" = - ] && claude_marketplace=
|
||||
[ "$codex_marketplace" = - ] && codex_marketplace=
|
||||
for client in "${clients[@]}"; do
|
||||
if [ "$client" = claude ]; then marketplace=$claude_marketplace; plugin=$claude_plugin; else marketplace=$codex_marketplace; plugin=$codex_plugin; fi
|
||||
[ -n "$plugin" ] || { printf 'Plugin selector missing for %s: %s\n' "$client" "$name" >&2; return 1; }
|
||||
if [ "$dry_run" = false ] && plugin_installed "$client" "$plugin"; then
|
||||
if [ "$update" = true ] && [ "$client" = claude ]; then
|
||||
run_plugin_command "$dry_run" claude plugin update "$plugin"
|
||||
run_plugin_command "$dry_run" claude plugin enable "$plugin"
|
||||
elif [ "$update" = true ] && [ "$client" = codex ]; then
|
||||
run_plugin_command "$dry_run" codex plugin add "$plugin"
|
||||
else
|
||||
printf 'PASS %s plugin already installed: %s\n' "$client" "$plugin"
|
||||
fi
|
||||
continue
|
||||
fi
|
||||
if [ "$client" = claude ]; then
|
||||
[ -z "$marketplace" ] || run_plugin_command "$dry_run" claude plugin marketplace add "$marketplace"
|
||||
run_plugin_command "$dry_run" claude plugin install "$plugin" --scope user
|
||||
else
|
||||
if [ -n "$marketplace" ] && [ "$marketplace" != openai-curated-remote ]; then
|
||||
marketplace_name=${plugin##*@}
|
||||
ensure_codex_marketplace "$dry_run" "$marketplace" "$marketplace_name"
|
||||
fi
|
||||
run_plugin_command "$dry_run" codex plugin add "$plugin"
|
||||
fi
|
||||
printf 'PASS %s plugin ensured: %s\n' "$client" "$plugin"
|
||||
done
|
||||
done < "$manifest"
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$root = Split-Path $PSScriptRoot -Parent
|
||||
$powerShellHook = Get-Content -LiteralPath (Join-Path $root 'shared/hooks/flashbang.ps1') -Raw
|
||||
$bashHook = Get-Content -LiteralPath (Join-Path $root 'shared/hooks/flashbang.sh') -Raw
|
||||
if ($powerShellHook -notmatch '\$HoldMs\s*=\s*250' -or $powerShellHook -notmatch '\$FadeMs\s*=\s*250' -or ([regex]::Matches($bashHook, 'default=250').Count -lt 2)) { throw 'Flashbang defaults must total 500 milliseconds on Windows and Linux.' }
|
||||
$statusInput = '{"model":{"display_name":"Test Model"},"effort":{"level":"high"},"workspace":{"current_dir":"' + $root.Replace('\','\\') + '","repo":{"name":"TestRepo"}},"context_window":{"context_window_size":200000,"used_percentage":8.5,"total_input_tokens":15500,"total_output_tokens":1200}}'
|
||||
$branch = & git -C $root branch --show-current
|
||||
$statusOutput = $statusInput | & (Join-Path $root 'shared/statusline/statusline.ps1')
|
||||
if ($statusOutput -ne "Model: Test Model | Effort: high | Repo: TestRepo | Branch: $branch | Max Context: 200000 | Used Context: 9% | Used Tokens: 16700") { throw 'PowerShell status line output is incorrect.' }
|
||||
foreach ($platform in @('windows','linux')) {
|
||||
foreach ($client in @('codex','claude')) {
|
||||
$package = Join-Path $root "generated/$client-$platform"
|
||||
$file = if ($client -eq 'codex') { 'config.toml' } else { 'settings.json' }
|
||||
$content = Get-Content -LiteralPath (Join-Path $package $file) -Raw
|
||||
if ($client -eq 'claude') { $settings = $content | ConvertFrom-Json }
|
||||
if (@(Get-ChildItem "$package/agents" -File).Count -ne 5) { throw "Missing agents in $package" }
|
||||
if (@(Get-ChildItem "$package/skills" -Filter SKILL.md -Recurse).Count -ne 22) { throw "Missing skills in $package" }
|
||||
$expected = if ($platform -eq 'windows') { 'powershell .*flashbang.ps1' } else { 'bash .*flashbang.sh' }
|
||||
if ($content -notmatch $expected -or $content -match '__HOOK_|__WINDOWS_HOOK_') { throw "Incorrect platform command in $package" }
|
||||
if ($platform -eq 'windows' -and $content -match 'WindowStyle\s+Hidden') { throw "Windows hook hides the terminal in $package" }
|
||||
if ($client -eq 'codex') {
|
||||
$events = @([regex]::Matches($content, '(?m)^\[\[hooks\.([^.\]]+)\]\]\s*$') | ForEach-Object { $_.Groups[1].Value })
|
||||
if ($events.Count -ne 1 -or $events[0] -ne 'Stop' -or $content -match 'flashbang-if-input' -or $content -match '(?m)^async\s*=\s*true\s*$') { throw "Codex finish hook is incorrect in $package" }
|
||||
if ($content -notmatch 'approvals_reviewer\s*=\s*"auto_review"') { throw "Codex auto review is missing in $package" }
|
||||
if ($content -notmatch 'status_line\s*=\s*\["model", "reasoning", "project-name", "git-branch", "context-window-size", "context-used", "used-tokens"\]') { throw "Codex status line is incorrect in $package" }
|
||||
} elseif (@($settings.hooks.PSObject.Properties.Name).Count -ne 1 -or $settings.hooks.PSObject.Properties.Name -ne 'Stop' -or $content -match 'flashbang-if-input' -or $settings.hooks.Stop[0].hooks[0].async) {
|
||||
throw "Claude finish hook is incorrect in $package"
|
||||
} elseif ($content -notmatch '"defaultMode"\s*:\s*"auto"') {
|
||||
throw "Claude auto permission mode is missing in $package"
|
||||
} elseif (-not (Test-Path -LiteralPath (Join-Path $package "statusline/statusline.$(if ($platform -eq 'windows') { 'ps1' } else { 'sh' })")) -or $settings.statusLine.command -notmatch "statusline\.$(if ($platform -eq 'windows') { 'ps1' } else { 'sh' })") {
|
||||
throw "Claude status line is incorrect in $package"
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($platformSelection in @('1','2')) {
|
||||
foreach ($clientSelection in @('1','2','3')) {
|
||||
$script:answers = [System.Collections.Generic.Queue[string]]::new()
|
||||
$script:answers.Enqueue($platformSelection)
|
||||
$script:answers.Enqueue($clientSelection)
|
||||
function Read-Host { param($Prompt) $answers.Dequeue() }
|
||||
$output = & "$PSScriptRoot/install.ps1" -DryRun
|
||||
if ($output -notcontains 'PASS install dry-run') { throw 'Dry-run did not finish.' }
|
||||
$platform = if ($platformSelection -eq '1') { 'windows' } else { 'linux' }
|
||||
if (($output -join "`n") -notmatch "-$platform") { throw 'Incorrect selected package.' }
|
||||
}
|
||||
}
|
||||
Write-Output 'PASS four platform packages and six PowerShell selections'
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
root=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)
|
||||
grep -Eq '\$HoldMs[[:space:]]*=[[:space:]]*250' "$root/shared/hooks/flashbang.ps1"
|
||||
grep -Eq '\$FadeMs[[:space:]]*=[[:space:]]*250' "$root/shared/hooks/flashbang.ps1"
|
||||
[ "$(grep -c 'default=250' "$root/shared/hooks/flashbang.sh")" -ge 2 ]
|
||||
branch=$(git -C "$root" branch --show-current)
|
||||
status_output=$(printf '{"model":{"display_name":"Test Model"},"effort":{"level":"high"},"workspace":{"current_dir":"%s","repo":{"name":"TestRepo"}},"context_window":{"context_window_size":200000,"used_percentage":8.5,"total_input_tokens":15500,"total_output_tokens":1200}}' "$root" | bash "$root/shared/statusline/statusline.sh")
|
||||
[ "$status_output" = "Model: Test Model | Effort: high | Repo: TestRepo | Branch: $branch | Max Context: 200000 | Used Context: 9% | Used Tokens: 16700" ]
|
||||
for platform in windows linux; do
|
||||
for client in codex claude; do
|
||||
package="$root/generated/$client-$platform"
|
||||
file=config.toml
|
||||
[ "$client" != claude ] || file=settings.json
|
||||
test -f "$package/$file"
|
||||
test "$(find "$package/agents" -type f | wc -l)" -eq 5
|
||||
test "$(find "$package/skills" -name SKILL.md | wc -l)" -eq 22
|
||||
if [ "$platform" = windows ]; then
|
||||
grep -q 'powershell .*flashbang.ps1' "$package/$file"
|
||||
! grep -Eq 'WindowStyle[[:space:]]+Hidden' "$package/$file"
|
||||
else
|
||||
grep -q 'bash .*flashbang.sh' "$package/$file"
|
||||
fi
|
||||
if [ "$client" = codex ]; then
|
||||
[ "$(sed -n 's/^\[\[hooks\.\([^].]*\)\]\]$/\1/p' "$package/$file")" = Stop ]
|
||||
! grep -q 'flashbang-if-input' "$package/$file"
|
||||
! grep -Eq '^async[[:space:]]*=[[:space:]]*true[[:space:]]*$' "$package/$file"
|
||||
grep -q 'approvals_reviewer[[:space:]]*=[[:space:]]*"auto_review"' "$package/$file"
|
||||
grep -Fq 'status_line = ["model", "reasoning", "project-name", "git-branch", "context-window-size", "context-used", "used-tokens"]' "$package/$file"
|
||||
else
|
||||
[ "$(awk '/^ "hooks": \{/{inside=1; next} inside && /^ \}/{inside=0} inside && /^ "[^"]+": \[$/{gsub(/^ "|": \[$/, ""); print}' "$package/$file")" = Stop ]
|
||||
! grep -q 'flashbang-if-input' "$package/$file"
|
||||
! grep -q '"async"[[:space:]]*:[[:space:]]*true' "$package/$file"
|
||||
grep -q '"defaultMode"[[:space:]]*:[[:space:]]*"auto"' "$package/$file"
|
||||
statusline_extension=sh
|
||||
[ "$platform" != windows ] || statusline_extension=ps1
|
||||
test -f "$package/statusline/statusline.$statusline_extension"
|
||||
grep -q "statusline.$statusline_extension" "$package/$file"
|
||||
fi
|
||||
if grep -Eq '__HOOK_|__WINDOWS_HOOK_' "$package/$file"; then exit 1; fi
|
||||
done
|
||||
done
|
||||
for platform_selection in 1 2; do
|
||||
for client_selection in 1 2 3; do
|
||||
output=$(printf '%s\n%s\n' "$platform_selection" "$client_selection" | bash "$root/scripts/install.sh" --dry-run)
|
||||
[[ "$output" == *'PASS install dry-run'* ]]
|
||||
platform=windows
|
||||
[ "$platform_selection" != 2 ] || platform=linux
|
||||
[[ "$output" == *"-$platform/"* ]]
|
||||
done
|
||||
done
|
||||
printf 'PASS four platform packages and six Bash selections\n'
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
name: architect
|
||||
description: Technical architecture and design
|
||||
role: architect
|
||||
write_permissions: read-only by default
|
||||
capabilities: boundaries, dependencies, interfaces, trade-offs, constraints, technical options
|
||||
delegation: ask the user about business behavior, user experience, APIs, data models, or configuration formats when certainty is incomplete
|
||||
@@ -0,0 +1,3 @@
|
||||
# Architect
|
||||
|
||||
Inspect the repository and requirements, identify technical boundaries and constraints, compare viable technical designs, and recommend the smallest maintainable architecture. Decide independently when evidence is sufficient, the choice is reversible, and no meaningful ambiguity remains. Ask the user about ambiguous business behavior, user-visible behavior, UI or UX, APIs, database models, configuration formats, compatibility behavior, or other high-impact unresolved choices. Do not invent business requirements.
|
||||
@@ -0,0 +1,6 @@
|
||||
name: implementer
|
||||
description: Execute engineering work
|
||||
role: implementer
|
||||
write_permissions: modify in the user-authorized workspace; ask before external writes
|
||||
capabilities: requirements analysis, implementation, verification, self-review
|
||||
delegation: use researcher, architect, reviewer, or verifier when their independent work is useful
|
||||
@@ -0,0 +1,3 @@
|
||||
# Implementer
|
||||
|
||||
Understand requirements and existing code, implement the smallest complete solution, follow applicable rules, run proportionate verification, and review your own changes. Preserve unrelated user work. Do not add comments or documentation without explicit user approval.
|
||||
@@ -0,0 +1,6 @@
|
||||
name: researcher
|
||||
description: Repository and technical investigation
|
||||
role: researcher
|
||||
write_permissions: read-only by default
|
||||
capabilities: repository inspection, pattern discovery, evidence gathering, approach comparison, unknown identification
|
||||
delegation: summarize findings before implementation when useful
|
||||
@@ -0,0 +1,3 @@
|
||||
# Researcher
|
||||
|
||||
Inspect existing code, established patterns, relevant implementations, documentation, and constraints. Gather evidence, compare viable approaches, identify unknowns, and summarize findings. Avoid modifying implementation code by default.
|
||||
@@ -0,0 +1,6 @@
|
||||
name: reviewer
|
||||
description: Independent quality review
|
||||
role: reviewer
|
||||
write_permissions: read-only by default
|
||||
capabilities: correctness, regressions, security, maintainability, architecture, tests, complexity
|
||||
delegation: review independently; do not blindly trust implementation claims
|
||||
@@ -0,0 +1,3 @@
|
||||
# Reviewer
|
||||
|
||||
When delegated, review the change independently. Check correctness, regressions, security, maintainability, architecture violations, insufficient tests, and unnecessary complexity. Report evidence, severity, and actionable findings. Do not modify implementation code unless explicitly assigned that work.
|
||||
@@ -0,0 +1,6 @@
|
||||
name: verifier
|
||||
description: Focused verification of completed work
|
||||
role: verifier
|
||||
write_permissions: read-only by default
|
||||
capabilities: acceptance criteria, tests, regressions, generated output, configuration, evidence
|
||||
delegation: verify the requested scope independently and report evidence and remaining uncertainty
|
||||
@@ -0,0 +1,3 @@
|
||||
# Verifier
|
||||
|
||||
Verify completed work against its requested behavior and acceptance criteria. Inspect the resulting changes, run the smallest relevant checks, verify generated and configuration output when applicable, and report evidence, failures, and remaining uncertainty. Do not change implementation code unless explicitly assigned that work.
|
||||
@@ -0,0 +1,32 @@
|
||||
# Personal global instructions
|
||||
|
||||
This instruction set is generated into the client-specific `AGENTS.md` and `CLAUDE.md` files. Do not edit generated copies.
|
||||
|
||||
Always load and apply `rules/general.md` before starting any task.
|
||||
|
||||
When programming, always load and apply `rules/security.md`. This includes implementing, modifying, debugging, reviewing, testing, and configuring software, scripts, hooks, infrastructure, and integrations.
|
||||
|
||||
Detect the languages, frameworks, tools, and change areas from the repository and the requested work. Load every applicable rule file before editing. Load all matching files when multiple technologies apply.
|
||||
|
||||
Load rule files when their subject applies:
|
||||
|
||||
- rules/angular.md for Angular work.
|
||||
- rules/typescript.md for TypeScript work.
|
||||
- rules/csharp.md for C# or .NET work.
|
||||
- rules/wpf.md for WPF work.
|
||||
- rules/ui-ux.md for UI or UX decisions.
|
||||
- rules/microsoft.md for Microsoft 365, Azure DevOps, or Teams work.
|
||||
- rules/git.md for Git operations.
|
||||
- rules/refactoring.md for refactoring work.
|
||||
- rules/definition-of-done.md when validating completion.
|
||||
- rules/decision-rule.md when requirements, behavior, or technical choices need to be evaluated.
|
||||
|
||||
Apply instructions in this order: direct current user instructions; security and data-loss protections; applicable project instructions; these global rules; existing project conventions; agent preferences.
|
||||
|
||||
Make evidence-based, reversible technical decisions independently. Ask when material uncertainty, multiple meaningful options, or high-impact irreversible effects remain. Ask about business behavior, user-visible behavior, UI, UX, APIs, database models, configuration formats, compatibility behavior, and other product decisions only when they are missing, ambiguous, contradictory, or open to interpretation. Implement explicitly specified behavior without asking again.
|
||||
|
||||
Never modify existing documentation automatically. Ask before a code change that would make existing documentation inaccurate. Create no new documentation, code comments, change summaries, pull request descriptions, work item text, or release notes without explicit user approval. If a comment appears necessary, ask first.
|
||||
|
||||
Project-specific instructions may specialize global defaults but must not weaken security or data-loss protections without explicit user approval. Direct user instructions have the highest priority for requested behavior.
|
||||
|
||||
Use implementer for execution and architect when technical boundaries or design options need dedicated analysis. Invoke researcher, reviewer, or verifier only when independent work is likely to improve the outcome. Decide based on uncertainty, complexity, risk, blast radius, and verification value; do not invoke these roles automatically. Parallelize only genuinely independent work.
|
||||
@@ -0,0 +1,3 @@
|
||||
# Hooks
|
||||
|
||||
Hooks are conservative entry points shared by clients. They validate obvious command hazards, check repository-local configuration inputs, and provide an optional post-change verification command. They do not bypass client permission prompts or grant access.
|
||||
@@ -0,0 +1,152 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Flashes the whole screen after an agent finishes responding.
|
||||
|
||||
.DESCRIPTION
|
||||
Draws a borderless, always-on-top, click-through window across every
|
||||
monitor, holds it at full brightness, then fades it out and exits.
|
||||
|
||||
The window is never activated and is transparent to input, so it cannot
|
||||
steal focus or swallow a keystroke or click from whatever you are doing.
|
||||
|
||||
.PARAMETER HoldMs
|
||||
Milliseconds to stay at full brightness before the fade starts.
|
||||
|
||||
.PARAMETER FadeMs
|
||||
Milliseconds the fade-out takes. Set to 0 for a hard cut.
|
||||
|
||||
.PARAMETER Color
|
||||
Flash color, as an HTML color name or hex ("White", "#FF0044").
|
||||
|
||||
.PARAMETER MaxOpacity
|
||||
Peak opacity, 0.0 - 1.0. Lower this if a full white flash is too much.
|
||||
|
||||
.PARAMETER PrimaryScreenOnly
|
||||
Flash only the primary monitor instead of all of them.
|
||||
|
||||
.EXAMPLE
|
||||
.\flashbang.ps1
|
||||
A default white flash across all monitors.
|
||||
|
||||
.EXAMPLE
|
||||
.\flashbang.ps1 -Color '#00E5FF' -MaxOpacity 0.55 -HoldMs 60 -FadeMs 300
|
||||
A gentler cyan pulse.
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[ValidateRange(0, 5000)] [int] $HoldMs = 250,
|
||||
[ValidateRange(0, 5000)] [int] $FadeMs = 250,
|
||||
[string] $Color = 'White',
|
||||
[ValidateRange(0.05, 1)] [double] $MaxOpacity = 0.35,
|
||||
[switch] $PrimaryScreenOnly
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
# PowerShell 6+ runs on Linux and macOS, where none of this applies.
|
||||
if ($PSVersionTable.PSVersion.Major -ge 6 -and -not $IsWindows) { exit 0 }
|
||||
|
||||
Add-Type -AssemblyName System.Windows.Forms, System.Drawing
|
||||
|
||||
# Compiling this shim costs about a second, which would show up as a full second
|
||||
# of lag before every flash. Emit it to a DLL once and load that from then on.
|
||||
$nativeSource = @'
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter,
|
||||
int X, int Y, int cx, int cy, uint uFlags);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
public static extern int GetWindowLong(IntPtr hWnd, int nIndex);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
|
||||
'@
|
||||
|
||||
if (-not ('Flashbang.Native' -as [type])) {
|
||||
# Keyed by host runtime: an assembly emitted by Windows PowerShell (.NET
|
||||
# Framework) is not guaranteed to load under pwsh (.NET), and vice versa.
|
||||
$cacheDir = Join-Path $env:LOCALAPPDATA 'claude-flashbang'
|
||||
$runtimeTag = '{0}{1}' -f $PSVersionTable.PSEdition, $PSVersionTable.PSVersion.Major
|
||||
$cacheDll = Join-Path $cacheDir "Flashbang.Native.$runtimeTag.dll"
|
||||
$loaded = $false
|
||||
|
||||
if (Test-Path -LiteralPath $cacheDll) {
|
||||
try { Add-Type -Path $cacheDll; $loaded = $true } catch { $loaded = $false }
|
||||
}
|
||||
|
||||
if (-not $loaded) {
|
||||
try {
|
||||
if (-not (Test-Path -LiteralPath $cacheDir)) {
|
||||
New-Item -ItemType Directory -Path $cacheDir -Force | Out-Null
|
||||
}
|
||||
Add-Type -Namespace 'Flashbang' -Name 'Native' -MemberDefinition $nativeSource `
|
||||
-OutputAssembly $cacheDll
|
||||
Add-Type -Path $cacheDll
|
||||
} catch {
|
||||
# Cache unavailable (locked file, no write access) - compile in-process.
|
||||
Add-Type -Namespace 'Flashbang' -Name 'Native' -MemberDefinition $nativeSource
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$HWND_TOPMOST = [IntPtr]::new(-1)
|
||||
$SWP_NOACTIVATE = 0x0010
|
||||
$SWP_SHOWWINDOW = 0x0040
|
||||
$GWL_EXSTYLE = -20
|
||||
$WS_EX_TRANSPARENT = 0x00000020 # clicks fall through to the window underneath
|
||||
$WS_EX_TOOLWINDOW = 0x00000080 # keep it out of Alt+Tab
|
||||
$WS_EX_NOACTIVATE = 0x08000000 # never take focus
|
||||
|
||||
try {
|
||||
$background = [System.Drawing.ColorTranslator]::FromHtml($Color)
|
||||
} catch {
|
||||
Write-Warning "Unrecognized color '$Color'; falling back to White."
|
||||
$background = [System.Drawing.Color]::White
|
||||
}
|
||||
|
||||
$bounds = if ($PrimaryScreenOnly) {
|
||||
[System.Windows.Forms.Screen]::PrimaryScreen.Bounds
|
||||
} else {
|
||||
[System.Windows.Forms.SystemInformation]::VirtualScreen
|
||||
}
|
||||
|
||||
$form = New-Object System.Windows.Forms.Form
|
||||
try {
|
||||
$form.FormBorderStyle = 'None'
|
||||
$form.StartPosition = 'Manual'
|
||||
$form.ShowInTaskbar = $false
|
||||
$form.BackColor = $background
|
||||
# Forces a layered window up front so Opacity animates without a handle rebuild.
|
||||
$form.AllowTransparency = $true
|
||||
$form.Opacity = $MaxOpacity
|
||||
$form.Bounds = $bounds
|
||||
|
||||
$handle = $form.Handle # touching Handle creates the window without showing it
|
||||
|
||||
$exStyle = [Flashbang.Native]::GetWindowLong($handle, $GWL_EXSTYLE)
|
||||
[void][Flashbang.Native]::SetWindowLong($handle, $GWL_EXSTYLE,
|
||||
($exStyle -bor $WS_EX_TRANSPARENT -bor $WS_EX_TOOLWINDOW -bor $WS_EX_NOACTIVATE))
|
||||
|
||||
[void][Flashbang.Native]::SetWindowPos($handle, $HWND_TOPMOST,
|
||||
$bounds.X, $bounds.Y, $bounds.Width, $bounds.Height,
|
||||
($SWP_NOACTIVATE -bor $SWP_SHOWWINDOW))
|
||||
[System.Windows.Forms.Application]::DoEvents()
|
||||
|
||||
$clock = [System.Diagnostics.Stopwatch]::StartNew()
|
||||
while ($clock.ElapsedMilliseconds -lt $HoldMs) {
|
||||
[System.Windows.Forms.Application]::DoEvents()
|
||||
Start-Sleep -Milliseconds 10
|
||||
}
|
||||
|
||||
if ($FadeMs -gt 0) {
|
||||
$clock.Restart()
|
||||
while ($clock.ElapsedMilliseconds -lt $FadeMs) {
|
||||
$progress = $clock.ElapsedMilliseconds / $FadeMs
|
||||
$form.Opacity = $MaxOpacity * (1 - $progress)
|
||||
[System.Windows.Forms.Application]::DoEvents()
|
||||
Start-Sleep -Milliseconds 8
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
$form.Dispose()
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Linux equivalent of flashbang.ps1. The visual overlay is implemented with
|
||||
# Python's standard tkinter module because Bash itself cannot create windows.
|
||||
# No third-party Python package is required.
|
||||
|
||||
if ! command -v python3 >/dev/null 2>&1; then
|
||||
command -v notify-send >/dev/null 2>&1 && notify-send 'AI assistant requires attention'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
exec python3 - "$@" <<'PY'
|
||||
import argparse
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tkinter as tk
|
||||
|
||||
|
||||
def notify_fallback() -> None:
|
||||
notify_send = shutil.which("notify-send")
|
||||
if notify_send:
|
||||
subprocess.run([notify_send, "AI assistant requires attention"], check=False)
|
||||
|
||||
|
||||
def monitor_bounds(primary_only: bool) -> tuple[int, int, int, int]:
|
||||
root = tk.Tk()
|
||||
root.withdraw()
|
||||
width = root.winfo_screenwidth()
|
||||
height = root.winfo_screenheight()
|
||||
root.destroy()
|
||||
|
||||
if primary_only or not shutil.which("xrandr"):
|
||||
return 0, 0, width, height
|
||||
|
||||
try:
|
||||
output = subprocess.run(
|
||||
["xrandr", "--current"],
|
||||
check=True,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
).stdout
|
||||
except (OSError, subprocess.SubprocessError):
|
||||
return 0, 0, width, height
|
||||
|
||||
monitors = [
|
||||
(int(w), int(h), int(x), int(y))
|
||||
for w, h, x, y in re.findall(r"(\d+)x(\d+)\+(-?\d+)\+(-?\d+)", output)
|
||||
]
|
||||
if not monitors:
|
||||
return 0, 0, width, height
|
||||
|
||||
left = min(x for _, _, x, _ in monitors)
|
||||
top = min(y for _, _, _, y in monitors)
|
||||
right = max(x + w for w, _, x, _ in monitors)
|
||||
bottom = max(y + h for _, h, _, y in monitors)
|
||||
return left, top, right - left, bottom - top
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(add_help=False)
|
||||
parser.add_argument("--hold-ms", type=int, default=250)
|
||||
parser.add_argument("--fade-ms", type=int, default=250)
|
||||
parser.add_argument("--color", default="white")
|
||||
parser.add_argument("--max-opacity", type=float, default=0.35)
|
||||
parser.add_argument("--primary-screen-only", action="store_true")
|
||||
args, _ = parser.parse_known_args()
|
||||
|
||||
args.hold_ms = max(0, min(5000, args.hold_ms))
|
||||
args.fade_ms = max(0, min(5000, args.fade_ms))
|
||||
args.max_opacity = max(0.05, min(1.0, args.max_opacity))
|
||||
|
||||
try:
|
||||
left, top, width, height = monitor_bounds(args.primary_screen_only)
|
||||
root = tk.Tk()
|
||||
root.overrideredirect(True)
|
||||
root.attributes("-topmost", True)
|
||||
root.attributes("-alpha", args.max_opacity)
|
||||
root.configure(background=args.color)
|
||||
root.geometry(f"{width}x{height}{left:+d}{top:+d}")
|
||||
root.withdraw()
|
||||
root.deiconify()
|
||||
root.lift()
|
||||
root.update()
|
||||
|
||||
def finish() -> None:
|
||||
root.destroy()
|
||||
|
||||
def fade(start_ms: int = 0) -> None:
|
||||
if args.fade_ms == 0:
|
||||
finish()
|
||||
return
|
||||
progress = min(1.0, start_ms / args.fade_ms)
|
||||
root.attributes("-alpha", args.max_opacity * (1.0 - progress))
|
||||
if progress >= 1.0:
|
||||
finish()
|
||||
else:
|
||||
root.after(8, fade, start_ms + 8)
|
||||
|
||||
root.after(args.hold_ms, fade)
|
||||
root.mainloop()
|
||||
return 0
|
||||
except (tk.TclError, RuntimeError, OSError, ValueError):
|
||||
# Headless sessions and minimal installations may not provide a usable
|
||||
# display or tkinter. Keep the hook non-blocking and informative.
|
||||
notify_fallback()
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
PY
|
||||
@@ -0,0 +1,7 @@
|
||||
param([string]$RepositoryRoot = (Split-Path $PSScriptRoot -Parent | Split-Path -Parent | Split-Path -Parent))
|
||||
$build = Join-Path $RepositoryRoot 'scripts/build.ps1'
|
||||
if (-not (Test-Path $build)) { Write-Error 'Build script is missing.'; exit 1 }
|
||||
$shellCommand = if ([Environment]::OSVersion.Platform -eq [PlatformID]::Win32NT) { 'powershell' } else { 'pwsh' }
|
||||
& $shellCommand -NoProfile -ExecutionPolicy Bypass -File $build
|
||||
if ($LASTEXITCODE) { exit $LASTEXITCODE }
|
||||
Write-Output 'PASS post-change verification'
|
||||
@@ -0,0 +1,5 @@
|
||||
param([string]$RepositoryRoot = (Split-Path $PSScriptRoot -Parent | Split-Path -Parent | Split-Path -Parent))
|
||||
$required = @('shared','adapters','scripts','docs','AGENTS.md')
|
||||
$missing = @($required | Where-Object { -not (Test-Path (Join-Path $RepositoryRoot $_)) })
|
||||
if ($missing.Count) { Write-Error ('Missing repository inputs: ' + ($missing -join ', ')); exit 1 }
|
||||
Write-Output 'PASS session configuration'
|
||||
@@ -0,0 +1,5 @@
|
||||
param([Parameter(Mandatory=$true)][string]$Command, [string]$Workspace = (Get-Location).Path)
|
||||
$dangerous = @('git reset --hard','git clean -fd','git clean -fx','Remove-Item -Recurse','rm -rf','format c:','del /s /q')
|
||||
foreach ($pattern in $dangerous) { if ($Command.IndexOf($pattern, [StringComparison]::OrdinalIgnoreCase) -ge 0) { Write-Error "Blocked potentially destructive command: $pattern"; exit 1 } }
|
||||
if ($Command -match '(?i)(^|\s)([A-Z]:\\|/)(?!.*' + [regex]::Escape($Workspace) + ')') { Write-Error 'Blocked command containing an absolute path outside the workspace.'; exit 1 }
|
||||
Write-Output 'PASS command safety'
|
||||
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
root=${1:?Repository root is required}
|
||||
bash "$root/scripts/build.sh"
|
||||
printf 'PASS post-change verification\n'
|
||||
@@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
root=${1:?Repository root is required}
|
||||
for path in shared adapters scripts docs AGENTS.md; do
|
||||
[ -e "$root/$path" ] || { printf 'Missing repository input: %s\n' "$path" >&2; exit 1; }
|
||||
done
|
||||
printf 'PASS session configuration\n'
|
||||
@@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
command_text=${1:?Command is required}
|
||||
workspace=${2:-$PWD}
|
||||
for pattern in 'git reset --hard' 'git clean -fd' 'git clean -fx' 'rm -rf' 'Remove-Item -Recurse' 'format c:' 'del /s /q'; do
|
||||
[[ ${command_text,,} != *"${pattern,,}"* ]] || { printf 'Blocked potentially destructive command: %s\n' "$pattern" >&2; exit 1; }
|
||||
done
|
||||
printf 'PASS command safety\n'
|
||||
@@ -0,0 +1,297 @@
|
||||
# Angular Code Guidelines
|
||||
|
||||
* Use modern Angular patterns and current framework conventions.
|
||||
* Prefer standalone components, directives and pipes for new code.
|
||||
* Avoid introducing `NgModule` unless the existing project architecture requires it.
|
||||
* Keep components small and focused.
|
||||
* Keep templates simple.
|
||||
* Move complex logic out of templates.
|
||||
* Keep business logic out of components where practical.
|
||||
* Prefer services, facades or dedicated domain logic for non-trivial behavior.
|
||||
* Avoid god components and god services.
|
||||
* Keep dependencies explicit.
|
||||
* Prefer composition over inheritance.
|
||||
* Avoid unnecessary abstractions.
|
||||
* Avoid unnecessary wrapper components.
|
||||
* Follow the existing project architecture unless there is a strong reason to change it.
|
||||
|
||||
## Components
|
||||
|
||||
* Use `ChangeDetectionStrategy.OnPush` unless there is a concrete reason not to.
|
||||
* Prefer signal-based state for local component state.
|
||||
* Prefer `computed` for derived state.
|
||||
* Prefer `effect` only for actual side effects.
|
||||
* Do not use `effect` as a replacement for normal data flow.
|
||||
* Keep component state minimal.
|
||||
* Avoid duplicating derived state.
|
||||
* Prefer immutable state updates.
|
||||
* Avoid direct mutation of shared state.
|
||||
* Keep inputs and outputs strongly typed.
|
||||
* Prefer signal-based inputs and outputs when consistent with the project.
|
||||
* Avoid unnecessary two-way binding.
|
||||
* Avoid unnecessary component-to-component coupling.
|
||||
* Prefer explicit data flow from parent to child and explicit events upward.
|
||||
* Do not expose internal component state unnecessarily.
|
||||
* Use lifecycle hooks only when required.
|
||||
* Avoid complex initialization logic inside constructors.
|
||||
|
||||
## Templates
|
||||
|
||||
* Keep expressions short and readable.
|
||||
* Do not execute expensive methods from templates.
|
||||
* Avoid function calls in templates when their result can be derived or cached.
|
||||
* Avoid complex conditions directly in markup.
|
||||
* Prefer derived state in TypeScript over repeated template expressions.
|
||||
* Use Angular control flow syntax such as `@if`, `@for` and `@switch` for new code.
|
||||
* Always provide stable tracking for repeated collections.
|
||||
* Avoid deeply nested template structures.
|
||||
* Split large templates into focused components when it improves maintainability.
|
||||
* Avoid unnecessary DOM elements.
|
||||
* Use semantic HTML.
|
||||
* Prefer native HTML behavior before custom implementations.
|
||||
* Keep accessibility in mind when choosing elements and interactions.
|
||||
|
||||
## Signals and State
|
||||
|
||||
* Prefer signals for local and synchronous reactive state.
|
||||
* Prefer `computed` for derived values.
|
||||
* Keep signals private when external mutation is not intended.
|
||||
* Expose readonly state where practical.
|
||||
* Avoid storing values that can be derived from existing state.
|
||||
* Avoid circular signal dependencies.
|
||||
* Avoid side effects inside `computed`.
|
||||
* Keep effects small and deterministic.
|
||||
* Clean up resources created by effects.
|
||||
* Do not use global state unless multiple unrelated parts of the application genuinely need it.
|
||||
* Do not introduce a state-management library without a clear requirement.
|
||||
|
||||
## RxJS
|
||||
|
||||
* Use RxJS for asynchronous streams, events and complex reactive flows.
|
||||
* Do not use RxJS when simple synchronous signals are sufficient.
|
||||
* Prefer declarative observable pipelines.
|
||||
* Avoid nested `subscribe`.
|
||||
* Avoid manual subscriptions where `async`, signals or framework helpers are sufficient.
|
||||
* Prefer `takeUntilDestroyed` or equivalent Angular lifecycle integration for manual subscriptions.
|
||||
* Always consider subscription lifetime.
|
||||
* Avoid memory leaks from unmanaged subscriptions.
|
||||
* Use the correct flattening operator for the required semantics.
|
||||
* Do not use `switchMap`, `mergeMap`, `concatMap` or `exhaustMap` interchangeably.
|
||||
* Avoid unnecessary `Subject` usage.
|
||||
* Prefer exposing observables instead of exposing mutable subjects.
|
||||
* Prefer `BehaviorSubject` only when a current value is actually required.
|
||||
* Avoid excessive observable chains for simple state.
|
||||
* Avoid converting repeatedly between signals and observables without need.
|
||||
|
||||
## Dependency Injection
|
||||
|
||||
* Prefer Angular dependency injection for application services.
|
||||
* Keep injected dependencies minimal.
|
||||
* Avoid service locator patterns.
|
||||
* Prefer `inject()` where it improves readability and is consistent with the project.
|
||||
* Do not inject services that are not used.
|
||||
* Scope services intentionally.
|
||||
* Prefer application-wide singletons only for truly shared stateless or coordinated state.
|
||||
* Avoid storing request-specific or component-specific mutable state in root services.
|
||||
* Use injection tokens for configuration or abstractions where appropriate.
|
||||
* Do not create interfaces only to satisfy dependency injection when no abstraction is needed.
|
||||
|
||||
## Services
|
||||
|
||||
* Keep services focused on a clear responsibility.
|
||||
* Avoid large catch-all services.
|
||||
* Separate API access, domain logic and UI state where practical.
|
||||
* Avoid leaking transport models throughout the application.
|
||||
* Do not expose mutable internal state directly.
|
||||
* Prefer readonly APIs for state consumers.
|
||||
* Avoid hidden side effects.
|
||||
* Keep service methods predictable.
|
||||
* Do not use services merely to move poorly structured component code elsewhere.
|
||||
|
||||
## HTTP and APIs
|
||||
|
||||
* Keep API access centralized and strongly typed.
|
||||
* Prefer dedicated API clients or data-access services.
|
||||
* Do not use `any` for API responses.
|
||||
* Treat all server responses as untrusted at runtime.
|
||||
* Validate external data when the contract is security- or correctness-critical.
|
||||
* Keep DTOs separate from domain models when their responsibilities differ.
|
||||
* Avoid duplicate API calls.
|
||||
* Cache only when the invalidation strategy is clear.
|
||||
* Avoid manual URL string construction when typed helpers or centralized endpoints are available.
|
||||
* Use interceptors only for cross-cutting concerns.
|
||||
* Do not put unrelated business logic into HTTP interceptors.
|
||||
* Handle cancellation where appropriate.
|
||||
* Handle expected error states explicitly.
|
||||
|
||||
## Forms
|
||||
|
||||
* Prefer reactive forms for non-trivial forms.
|
||||
* Keep forms strongly typed.
|
||||
* Avoid untyped forms.
|
||||
* Keep validation rules centralized and reusable where practical.
|
||||
* Validate on both client and server where required.
|
||||
* Never treat client-side validation as a security boundary.
|
||||
* Keep form state separate from domain state when useful.
|
||||
* Avoid large components that combine layout, validation, persistence and business logic.
|
||||
* Display validation errors consistently.
|
||||
* Preserve user input when recoverable errors occur.
|
||||
|
||||
## Routing
|
||||
|
||||
* Keep route definitions explicit and predictable.
|
||||
* Prefer lazy loading for larger feature areas.
|
||||
* Avoid loading large feature bundles eagerly without need.
|
||||
* Use route guards only for navigation behavior, not as a security boundary.
|
||||
* Authorization must still be enforced on the backend.
|
||||
* Keep resolvers focused.
|
||||
* Avoid expensive work during navigation unless required.
|
||||
* Keep route parameters strongly typed at application boundaries where practical.
|
||||
* Do not rely on client-side routing state for sensitive authorization decisions.
|
||||
|
||||
## Performance
|
||||
|
||||
* Use `OnPush`.
|
||||
* Use stable tracking in loops.
|
||||
* Avoid unnecessary change detection triggers.
|
||||
* Avoid repeated expensive template calculations.
|
||||
* Avoid unnecessary subscriptions.
|
||||
* Avoid unnecessary DOM rendering.
|
||||
* Lazy-load large features and heavy dependencies where appropriate.
|
||||
* Avoid large initial bundles.
|
||||
* Avoid importing full libraries when only a small part is required.
|
||||
* Avoid unnecessary deep cloning.
|
||||
* Avoid unnecessary object and array recreation in hot paths.
|
||||
* Keep state updates targeted.
|
||||
* Avoid unnecessary global state updates.
|
||||
* Measure bundle size and runtime performance before micro-optimizing.
|
||||
* Prefer architectural improvements over template-level micro-optimizations.
|
||||
|
||||
## Security
|
||||
|
||||
* Treat all external data as untrusted.
|
||||
* Never bypass Angular sanitization without a verified reason.
|
||||
* Avoid direct DOM manipulation.
|
||||
* Avoid `innerHTML` with untrusted content.
|
||||
* Avoid `bypassSecurityTrust*` unless explicitly required and the input is fully controlled.
|
||||
* Never expose secrets in frontend code.
|
||||
* Never store sensitive credentials in the Angular application.
|
||||
* Do not rely on frontend checks for authorization.
|
||||
* Enforce authentication and authorization on the backend.
|
||||
* Avoid leaking sensitive information through logs or error messages.
|
||||
* Use secure cookie or token handling according to the application's authentication architecture.
|
||||
* Avoid storing sensitive tokens in insecure browser storage without a deliberate security decision.
|
||||
* Do not disable security controls for convenience.
|
||||
|
||||
## DOM and Browser APIs
|
||||
|
||||
* Prefer Angular APIs and declarative templates over direct DOM manipulation.
|
||||
* Use `Renderer2` only when direct rendering abstraction is actually needed.
|
||||
* Avoid accessing globals directly when it harms testability or SSR compatibility.
|
||||
* Consider SSR and hydration compatibility for browser-specific code.
|
||||
* Guard access to `window`, `document`, `localStorage` and similar browser-only APIs when SSR is supported.
|
||||
* Clean up event listeners, observers and timers.
|
||||
* Avoid layout thrashing in performance-sensitive code.
|
||||
|
||||
## Accessibility
|
||||
|
||||
* Use semantic HTML.
|
||||
* Preserve keyboard navigation.
|
||||
* Ensure interactive elements are actually interactive elements.
|
||||
* Do not replace buttons with clickable `div` elements.
|
||||
* Provide labels for form controls.
|
||||
* Maintain visible focus behavior.
|
||||
* Use ARIA only when native HTML semantics are insufficient.
|
||||
* Avoid unnecessary custom widgets.
|
||||
* Keep accessible names and states synchronized with UI state.
|
||||
|
||||
## Styling
|
||||
|
||||
* Keep styles scoped and predictable.
|
||||
* Avoid unnecessary global CSS.
|
||||
* Follow the project's styling strategy consistently.
|
||||
* Avoid excessive specificity.
|
||||
* Avoid `!important` unless there is a concrete reason.
|
||||
* Prefer reusable design tokens and shared styles over duplicated magic values.
|
||||
* Keep component styles focused on component concerns.
|
||||
* Avoid styling based on fragile DOM structure.
|
||||
* Do not mix multiple styling approaches without need.
|
||||
|
||||
## Testing
|
||||
|
||||
* Test behavior, not implementation details.
|
||||
* Prefer focused component tests.
|
||||
* Test critical user interactions.
|
||||
* Test services and domain logic independently where useful.
|
||||
* Avoid brittle tests coupled to internal structure.
|
||||
* Avoid excessive mocking.
|
||||
* Mock external boundaries rather than internal implementation details.
|
||||
* Keep tests deterministic.
|
||||
* Avoid time-dependent tests without controlled clocks.
|
||||
* Avoid network-dependent tests without proper isolation.
|
||||
* Keep test setup minimal and readable.
|
||||
* Update tests when refactoring changes structure but not behavior.
|
||||
|
||||
## Architecture
|
||||
|
||||
* Keep UI, application, domain and data-access concerns separated where practical.
|
||||
* Organize code by feature rather than by technical file type when it improves cohesion.
|
||||
* Avoid circular dependencies.
|
||||
* Avoid cross-feature imports without a clear contract.
|
||||
* Keep shared code genuinely shared.
|
||||
* Do not move feature-specific logic into generic shared modules.
|
||||
* Avoid dumping unrelated helpers into global utility files.
|
||||
* Keep public APIs of feature areas small.
|
||||
* Avoid exposing internal implementation details across feature boundaries.
|
||||
* Prefer local ownership of state and logic.
|
||||
|
||||
## Code Quality
|
||||
|
||||
* Use strict TypeScript settings.
|
||||
* Avoid `any`.
|
||||
* Avoid unnecessary type assertions.
|
||||
* Avoid non-null assertions unless safety is guaranteed.
|
||||
* Prefer modern, readable syntax.
|
||||
* Use descriptive names.
|
||||
* Avoid vague names such as `data`, `item`, `value` or `temp` when better names exist.
|
||||
* Remove dead code.
|
||||
* Remove unused imports and dependencies.
|
||||
* Remove commented-out code instead of keeping it in source files.
|
||||
* Do not add comments unless the user explicitly requests them.
|
||||
* Treat Angular, TypeScript and lint warnings seriously.
|
||||
* Do not suppress diagnostics without a concrete reason.
|
||||
* Prefer correctness, security and maintainability over cleverness.
|
||||
|
||||
## Dependency Rules
|
||||
|
||||
* Prefer Angular and browser platform capabilities before adding third-party libraries.
|
||||
* Do not add dependencies without a clear benefit.
|
||||
* Avoid libraries that duplicate existing framework functionality.
|
||||
* Avoid abandoned or poorly maintained packages.
|
||||
* Keep Angular package versions aligned.
|
||||
* Do not mix incompatible Angular package versions.
|
||||
* Respect the existing lockfile and package manager.
|
||||
* Avoid unrelated dependency upgrades.
|
||||
|
||||
## Performance Priority
|
||||
|
||||
Prioritize Angular performance work in this order:
|
||||
|
||||
* Application architecture
|
||||
* Network and API behavior
|
||||
* Bundle size and lazy loading
|
||||
* State architecture
|
||||
* Change detection
|
||||
* Rendering and DOM complexity
|
||||
* RxJS and subscription behavior
|
||||
* Memory allocations
|
||||
* CPU micro-optimizations
|
||||
|
||||
Never optimize based purely on assumptions.
|
||||
|
||||
## Safety Rule
|
||||
|
||||
* Angular frontend code is never a security boundary.
|
||||
* Client-side validation, guards, hidden controls and disabled UI elements do not replace backend enforcement.
|
||||
* Do not bypass Angular's built-in security mechanisms without a verified and explicit reason.
|
||||
* Prefer safe framework defaults over custom low-level behavior.
|
||||
@@ -0,0 +1,116 @@
|
||||
# C# Code Guidelines
|
||||
|
||||
* Write clear, readable, maintainable code first.
|
||||
* Optimize only based on measurements and profiling.
|
||||
* Prefer simple solutions over clever abstractions.
|
||||
* Follow current C# and .NET conventions.
|
||||
* Prefer immutable data where practical.
|
||||
* Keep methods small and focused.
|
||||
* Keep classes focused on a single responsibility.
|
||||
* Avoid unnecessary inheritance.
|
||||
* Prefer composition over inheritance.
|
||||
* Use `sealed` when inheritance is not intended.
|
||||
* Avoid unnecessary abstractions and wrapper layers.
|
||||
* Avoid premature generalization.
|
||||
* Prefer explicit code over hidden magic.
|
||||
* Avoid unnecessary reflection.
|
||||
* Avoid unnecessary runtime type checks.
|
||||
* Avoid unnecessary allocations in hot paths.
|
||||
* Avoid unnecessary collection copies.
|
||||
* Avoid unnecessary string allocations.
|
||||
* Avoid unnecessary LINQ in performance-critical paths.
|
||||
* Use LINQ where it improves readability and performance is irrelevant.
|
||||
* Choose collections based on access patterns.
|
||||
* Preallocate collection capacity when the expected size is known.
|
||||
* Avoid large mutable structs.
|
||||
* Use `Span<T>` and related APIs only when they provide a measurable benefit.
|
||||
* Prefer `Task` over `ValueTask` unless `ValueTask` is justified by profiling.
|
||||
* Use async only for genuinely asynchronous operations.
|
||||
* Keep async code async throughout the call chain.
|
||||
* Avoid `.Result`, `.Wait()` and synchronous blocking of async operations.
|
||||
* Propagate `CancellationToken` through asynchronous APIs.
|
||||
* Do not create unnecessary background tasks.
|
||||
* Limit concurrency when processing large workloads.
|
||||
* Avoid uncontrolled `Task.WhenAll` over large collections.
|
||||
* Avoid exceptions for normal control flow.
|
||||
* Fail fast on invalid arguments and invalid state.
|
||||
* Avoid swallowing exceptions.
|
||||
* Preserve meaningful exception context.
|
||||
* Use dependency injection where dependencies require substitution or lifecycle management.
|
||||
* Avoid service locator patterns.
|
||||
* Avoid excessive constructor dependencies.
|
||||
* Keep application, domain and infrastructure concerns separated.
|
||||
* Avoid unnecessary cross-layer coupling.
|
||||
* Prefer explicit dependencies.
|
||||
* Minimize global and static mutable state.
|
||||
* Design APIs with clear contracts.
|
||||
* Prefer strongly typed models over loosely typed dictionaries or dynamic objects.
|
||||
* Validate input at system boundaries.
|
||||
* Avoid duplicate validation deep inside trusted internal code.
|
||||
* Treat external input as untrusted.
|
||||
* Do not expose internal implementation details through public APIs.
|
||||
* Avoid leaking sensitive information through logs or exceptions.
|
||||
* Use structured logging.
|
||||
* Avoid excessive logging in hot paths.
|
||||
* Avoid logging sensitive data.
|
||||
* Prefer database-side filtering, projection and aggregation.
|
||||
* Do not load data that is not needed.
|
||||
* Avoid N+1 database queries.
|
||||
* Use no-tracking queries for read-only EF Core operations where appropriate.
|
||||
* Keep database round trips minimal.
|
||||
* Avoid unnecessary serialization and deserialization.
|
||||
* Reuse expensive resources such as HTTP clients and database infrastructure correctly.
|
||||
* Do not optimize micro-level CPU operations before fixing architectural, database or I/O bottlenecks.
|
||||
* Prefer algorithms and data structures with appropriate complexity.
|
||||
* Measure allocations, GC pressure, CPU usage and latency when investigating performance.
|
||||
* Write code that is easy to test.
|
||||
* Avoid tests coupled to implementation details.
|
||||
* Prefer deterministic behavior.
|
||||
* Avoid hidden side effects.
|
||||
* Keep naming consistent and descriptive.
|
||||
* Avoid abbreviations unless they are established domain terminology.
|
||||
* Remove dead code instead of keeping it as commented-out code.
|
||||
* Do not add comments or API documentation unless the user explicitly requests them.
|
||||
* Follow existing project conventions unless there is a strong reason to change them.
|
||||
* Do not introduce new libraries when the BCL or existing dependencies already solve the problem adequately.
|
||||
* Prefer fewer dependencies.
|
||||
* Keep dependency versions current and supported.
|
||||
* Treat warnings seriously.
|
||||
* Do not suppress analyzers without a concrete reason.
|
||||
* Keep performance improvements readable unless the hot path clearly justifies additional complexity.
|
||||
* Prefer correctness, maintainability and predictable behavior over theoretical micro-optimizations.
|
||||
|
||||
## C# Style & Safety
|
||||
|
||||
* Prefer modern, readable C# syntax and current .NET conventions.
|
||||
* Prefer simple, explicit code over outdated or unnecessarily verbose patterns.
|
||||
* Prefer concrete collection types for parameters, properties and local APIs when no abstraction is required.
|
||||
* Avoid interface collection types such as `IDictionary<TKey, TValue>`, `IList<T>` or `ICollection<T>` unless polymorphism or API abstraction is actually needed.
|
||||
* Prefer `Dictionary<TKey, TValue>`, `List<T>`, arrays or other concrete types when the implementation type is known and intentional.
|
||||
* Prefer strongly typed models over `object`, `dynamic`, loosely typed dictionaries or string-based contracts.
|
||||
* Validate external input at system boundaries.
|
||||
* Fail fast on invalid arguments and impossible states.
|
||||
* Avoid unsafe code unless explicitly required.
|
||||
* Avoid reflection when a strongly typed solution is practical.
|
||||
* Avoid hidden side effects and implicit global state.
|
||||
* Prefer immutable or readonly data where practical.
|
||||
* Avoid exposing mutable internal collections directly.
|
||||
* Prefer safe framework APIs over custom low-level implementations.
|
||||
* Never weaken validation, authorization, certificate checks, encryption or other security controls for convenience.
|
||||
* Do not log secrets, tokens, credentials or sensitive data.
|
||||
* Treat all external data as untrusted.
|
||||
* Prefer correctness and security over minor convenience or micro-optimizations.
|
||||
|
||||
## Performance Priority
|
||||
|
||||
Prioritize performance work in this order:
|
||||
|
||||
* Architecture
|
||||
* Database access
|
||||
* Network and I/O
|
||||
* Algorithms and data structures
|
||||
* Concurrency
|
||||
* Allocations and GC pressure
|
||||
* CPU micro-optimizations
|
||||
|
||||
Never optimize based purely on assumptions.
|
||||
@@ -0,0 +1,10 @@
|
||||
## Decision Rule
|
||||
|
||||
* Gather evidence from the repository, available tooling, and current technical sources before making technical decisions.
|
||||
* Make technical implementation and code-style decisions independently when existing code, reliable documentation, or established standards provide sufficient evidence and the decision is reversible.
|
||||
* Ask the user when technical uncertainty remains material, multiple meaningful options remain, or the decision has a high-impact or difficult-to-reverse effect.
|
||||
* Ask the user before deciding business behavior, domain rules, validation rules, status transitions, permissions, database rules, error behavior, UI, UX, or other user-visible behavior when the requested behavior is missing, ambiguous, contradictory, or open to interpretation.
|
||||
* Implement explicitly specified behavior without asking again.
|
||||
* Ask the user when changing or choosing an API, database model, configuration format, external contract, or compatibility behavior remains ambiguous or has multiple meaningful interpretations.
|
||||
* Do not invent business requirements or silently resolve contradictions.
|
||||
* Treat direct user input as the final decision for behavior and requirements.
|
||||
@@ -0,0 +1,52 @@
|
||||
# Definition of Done
|
||||
|
||||
A task is only considered done when all applicable requirements below are fulfilled.
|
||||
|
||||
## Coding
|
||||
|
||||
* The implementation fully satisfies the requested behavior.
|
||||
* All relevant acceptance criteria are implemented.
|
||||
* The work item description is fully addressed.
|
||||
* The code builds successfully.
|
||||
* Relevant tests pass.
|
||||
* New or changed behavior is covered by tests where appropriate.
|
||||
* No known errors, warnings, regressions, or broken behavior remain.
|
||||
* The implementation follows the project's coding, architecture, security, and performance guidelines.
|
||||
* No unrelated changes are included.
|
||||
* No temporary code, debug output, commented-out code, placeholders, or TODOs remain unless explicitly intended.
|
||||
* Error handling and edge cases are handled appropriately.
|
||||
* The implementation is readable, maintainable, and production-ready.
|
||||
* Existing documentation was not changed automatically. If the code makes it inaccurate, the user was asked before proceeding.
|
||||
* No new documentation, repository comments, pull request text, or work-item text was created without explicit user instruction.
|
||||
* Any delegated research, review, or verification is complete and its relevant findings are resolved or reported.
|
||||
|
||||
## Work Items
|
||||
|
||||
A work item is only considered complete when:
|
||||
|
||||
* Every acceptance criterion is fulfilled.
|
||||
* Every requirement in the description is implemented or otherwise resolved.
|
||||
* Acceptance criteria and description are checked against the actual implementation, not assumed to be complete.
|
||||
* No known requirement is left partially implemented.
|
||||
* No unresolved blocker or relevant defect remains.
|
||||
* Required tests or validations have been completed successfully.
|
||||
* Any deviation from the description or acceptance criteria has been explicitly approved by the user.
|
||||
|
||||
## Completion Check
|
||||
|
||||
Before declaring a task complete:
|
||||
|
||||
* Re-read the work item description.
|
||||
* Re-read all acceptance criteria.
|
||||
* Compare each requirement against the implemented result.
|
||||
* Verify the relevant code paths.
|
||||
* Run applicable builds and tests.
|
||||
* Check for incomplete or unrelated changes.
|
||||
* Confirm that the final state matches the requested outcome.
|
||||
|
||||
## Important Rule
|
||||
|
||||
* Do not mark, close, resolve, or otherwise change the state of a work item automatically.
|
||||
* A task may be technically complete without changing its remote work item state.
|
||||
* Any Azure DevOps WRITE operation still requires explicit user approval.
|
||||
* If completion is unclear, requirements conflict, or something is missing, ask the user instead of deciding autonomously.
|
||||
@@ -0,0 +1,32 @@
|
||||
# General rules
|
||||
|
||||
## Priority
|
||||
|
||||
Apply instructions in this order:
|
||||
|
||||
1. Direct current user instructions.
|
||||
2. Non-negotiable security and data-loss protections.
|
||||
3. Applicable project-specific instructions.
|
||||
4. These global user-level rules.
|
||||
5. Existing project conventions.
|
||||
6. Agent preferences.
|
||||
|
||||
Project instructions may specialize global defaults, but must not weaken security or data-loss protections without explicit user approval.
|
||||
|
||||
## Documentation
|
||||
|
||||
* Never modify existing documentation automatically.
|
||||
* If a code change would make existing documentation inaccurate or outdated, ask the user before changing the code or documentation.
|
||||
* Do not create new documentation unless the user explicitly requests it.
|
||||
* This includes README files, technical documentation, changelogs, release notes, pull request descriptions, and work-item text.
|
||||
|
||||
## Comments
|
||||
|
||||
* Do not add new code comments without the user's explicit approval.
|
||||
* This includes `why` comments, workaround explanations, framework limitations, and external constraints.
|
||||
* If a comment appears technically useful or necessary, ask the user before adding it.
|
||||
* Prefer self-explanatory code and clear names.
|
||||
|
||||
## Language
|
||||
|
||||
* Write code and repository-generated user-facing text in English.
|
||||
@@ -0,0 +1,167 @@
|
||||
# Git Guidelines
|
||||
|
||||
## General Rules
|
||||
|
||||
* Never commit changes unless explicitly instructed to do so.
|
||||
* Never push changes unless explicitly instructed to do so.
|
||||
* Never create a pull request unless explicitly instructed to do so.
|
||||
* Never merge branches unless explicitly instructed to do so.
|
||||
* Never rebase branches unless explicitly instructed to do so.
|
||||
* Never amend an existing commit unless explicitly instructed to do so.
|
||||
* Never create or delete Git tags unless explicitly instructed to do so.
|
||||
* Never modify remote branches unless explicitly instructed to do so.
|
||||
* Do not interpret general requests such as "finish this", "implement this", or "fix this" as permission to commit or push.
|
||||
* Permission to commit does not imply permission to push.
|
||||
* Permission to push does not imply permission to create or merge a pull request.
|
||||
* Only perform Git write operations that the user explicitly requested.
|
||||
* Read-only Git commands may be used when needed to inspect repository state.
|
||||
|
||||
## Repository Safety
|
||||
|
||||
* Always inspect the current Git status before performing Git write operations.
|
||||
* Never discard uncommitted user changes.
|
||||
* Never overwrite unrelated changes.
|
||||
* Never reset, clean, checkout, restore, or revert user changes unless explicitly requested.
|
||||
* Never use destructive Git operations without explicit instruction.
|
||||
* Never use `git reset --hard` unless explicitly requested.
|
||||
* Never use `git clean` unless explicitly requested.
|
||||
* Never force-push unless explicitly requested.
|
||||
* Never use `--force` or `--force-with-lease` unless explicitly requested.
|
||||
* Never rewrite shared history without explicit instruction.
|
||||
* Never modify `.gitignore` unless required by the task.
|
||||
* Never commit secrets, credentials, tokens, API keys, private keys, environment files, or other sensitive data.
|
||||
* Never bypass Git hooks unless explicitly requested.
|
||||
* Never use `--no-verify` unless explicitly requested.
|
||||
|
||||
## Scope
|
||||
|
||||
* Only stage files related to the requested task.
|
||||
* Never stage unrelated modified files.
|
||||
* Prefer staging specific files instead of using broad commands such as `git add .`.
|
||||
* Do not include generated files unless they are intentionally tracked by the repository.
|
||||
* Do not include formatting-only changes unrelated to the task.
|
||||
* Do not modify unrelated files merely to create a cleaner commit.
|
||||
* Keep commits focused on one logical change.
|
||||
* Split unrelated changes into separate commits when multiple commits were explicitly requested.
|
||||
|
||||
## Commit Messages
|
||||
|
||||
Use Conventional Commits.
|
||||
|
||||
Format:
|
||||
|
||||
`<type>(<optional-scope>): <description>`
|
||||
|
||||
Allowed common types:
|
||||
|
||||
* `feat`: new functionality
|
||||
* `fix`: bug fix
|
||||
* `refactor`: code change without changing external behavior
|
||||
* `perf`: performance improvement
|
||||
* `test`: test changes
|
||||
* `docs`: documentation changes
|
||||
* `style`: formatting or style-only changes
|
||||
* `build`: build system or dependency changes
|
||||
* `ci`: CI/CD changes
|
||||
* `chore`: maintenance work
|
||||
* `revert`: revert of an earlier change
|
||||
|
||||
Commit message rules:
|
||||
|
||||
* Use lowercase commit types.
|
||||
* Keep the subject concise and specific.
|
||||
* Use imperative wording.
|
||||
* Do not end the subject with a period.
|
||||
* Describe what changed, not how hard the work was.
|
||||
* Avoid vague messages such as `fix stuff`, `update`, `changes`, or `cleanup`.
|
||||
* Use a scope when it improves clarity.
|
||||
* Keep each commit limited to one logical purpose.
|
||||
* Use `!` or a `BREAKING CHANGE:` footer for breaking changes.
|
||||
* Reference issue or ticket identifiers only when relevant and known.
|
||||
* Never invent issue numbers, ticket IDs, or references.
|
||||
|
||||
Examples of valid commit messages:
|
||||
|
||||
* `feat(auth): add refresh token rotation`
|
||||
* `fix(api): handle missing user id`
|
||||
* `refactor(storage): simplify cache abstraction`
|
||||
* `perf(database): reduce duplicate queries`
|
||||
* `test(users): add validation coverage`
|
||||
* `docs(readme): document local setup`
|
||||
* `build: update dotnet dependencies`
|
||||
|
||||
## Branches
|
||||
|
||||
* Do not create a branch unless explicitly requested.
|
||||
* Do not switch branches unless necessary for the requested task.
|
||||
* Never delete branches unless explicitly requested.
|
||||
* Never rename branches unless explicitly requested.
|
||||
* Never assume the target branch for a merge, rebase, or push.
|
||||
* Preserve the repository's existing branch naming convention.
|
||||
* If no branch naming convention exists and a branch was explicitly requested, prefer concise names such as:
|
||||
|
||||
* `feat/<name>`
|
||||
* `fix/<name>`
|
||||
* `refactor/<name>`
|
||||
* `chore/<name>`
|
||||
|
||||
## Pulling and Fetching
|
||||
|
||||
* Fetching remote state is allowed when required for inspection.
|
||||
* Do not pull automatically unless explicitly requested or required for an explicitly requested Git operation.
|
||||
* Never resolve pull or merge conflicts by discarding user changes.
|
||||
* Do not automatically rebase after pulling.
|
||||
* Do not automatically merge remote changes into the current branch.
|
||||
|
||||
## Conflicts
|
||||
|
||||
* Stop before making destructive conflict-resolution decisions.
|
||||
* Preserve both user work and repository history whenever possible.
|
||||
* Resolve conflicts only when the correct resolution is clear from the task and surrounding code.
|
||||
* Do not silently choose one side of a conflict when intent is ambiguous.
|
||||
* Never use conflict resolution as an excuse to remove unrelated changes.
|
||||
|
||||
## Before an Explicitly Requested Commit
|
||||
|
||||
Before creating a commit:
|
||||
|
||||
* Inspect `git status`.
|
||||
* Inspect the staged diff.
|
||||
* Confirm only task-related files are staged.
|
||||
* Check for accidental secrets or sensitive files.
|
||||
* Ensure the changes are consistent with the requested task.
|
||||
* Run relevant tests, checks, or builds when practical.
|
||||
* Do not include unrelated modifications.
|
||||
* Use a Conventional Commit message.
|
||||
|
||||
## Before an Explicitly Requested Push
|
||||
|
||||
Before pushing:
|
||||
|
||||
* Confirm that pushing was explicitly requested.
|
||||
* Confirm the intended branch.
|
||||
* Confirm the intended remote when multiple remotes exist.
|
||||
* Ensure the commits being pushed are expected.
|
||||
* Do not force-push unless explicitly requested.
|
||||
* Do not push unrelated local commits unintentionally.
|
||||
|
||||
## Autonomous Agent Rule
|
||||
|
||||
The agent may edit files and implement requested changes autonomously.
|
||||
|
||||
The agent must not autonomously:
|
||||
|
||||
* commit
|
||||
* push
|
||||
* merge
|
||||
* rebase
|
||||
* amend commits
|
||||
* create pull requests
|
||||
* create or delete tags
|
||||
* delete branches
|
||||
* rewrite Git history
|
||||
* discard working-tree changes
|
||||
|
||||
These actions require explicit user instruction each time.
|
||||
|
||||
When in doubt, leave the repository changes uncommitted.
|
||||
@@ -0,0 +1,133 @@
|
||||
# Azure DevOps & Microsoft Teams Guidelines
|
||||
|
||||
## Core Rule
|
||||
|
||||
* READ operations may be performed autonomously.
|
||||
* WRITE operations always require explicit user confirmation beforehand.
|
||||
* Treat all remote data as read-only by default.
|
||||
* Never perform a WRITE operation without asking first.
|
||||
* Previous approval does not automatically authorize future WRITE operations.
|
||||
* If the intended WRITE changes materially after approval, ask again.
|
||||
|
||||
## READ Operations
|
||||
|
||||
READ operations may be performed without confirmation.
|
||||
|
||||
Examples:
|
||||
|
||||
* Read work items
|
||||
* Read descriptions
|
||||
* Read comments
|
||||
* Read pull requests
|
||||
* Read pipeline status
|
||||
* Read repository metadata
|
||||
* Read Teams messages
|
||||
* Read conversations and threads
|
||||
* Read meeting information
|
||||
* Search Azure DevOps
|
||||
* Search Microsoft Teams
|
||||
* Inspect statuses, assignments, tags, fields and history
|
||||
* Analyze retrieved information
|
||||
|
||||
Do not ask for permission before READ operations when they are useful for completing the task.
|
||||
|
||||
## WRITE Operations
|
||||
|
||||
Before every WRITE operation:
|
||||
|
||||
* Explain exactly what will be changed.
|
||||
* Show the intended content when applicable.
|
||||
* Ask for explicit confirmation.
|
||||
* Perform the WRITE only after confirmation.
|
||||
* Do not assume approval from context or previous actions.
|
||||
|
||||
WRITE operations include any action that changes remote state.
|
||||
|
||||
## Azure DevOps WRITE Operations
|
||||
|
||||
Always ask before:
|
||||
|
||||
* Creating work items
|
||||
* Editing work items
|
||||
* Editing titles
|
||||
* Editing descriptions
|
||||
* Editing acceptance criteria
|
||||
* Adding comments
|
||||
* Replying to comments
|
||||
* Editing or deleting comments
|
||||
* Changing status or state
|
||||
* Opening or reopening work items
|
||||
* Resolving or closing work items
|
||||
* Assigning or reassigning work items
|
||||
* Changing priority, severity, tags, iteration or area
|
||||
* Modifying links or relations
|
||||
* Creating or modifying pull requests
|
||||
* Approving or voting on pull requests
|
||||
* Completing, merging or abandoning pull requests
|
||||
* Triggering, retrying or cancelling pipelines
|
||||
* Modifying pipeline configuration
|
||||
* Creating or deleting branches
|
||||
* Modifying repository settings
|
||||
* Modifying policies, releases, environments or deployments
|
||||
* Any other operation that changes Azure DevOps data
|
||||
|
||||
## Microsoft Teams WRITE Operations
|
||||
|
||||
Always ask before:
|
||||
|
||||
* Sending messages
|
||||
* Replying to messages
|
||||
* Editing messages
|
||||
* Deleting messages
|
||||
* Reacting to messages
|
||||
* Creating posts or announcements
|
||||
* Creating chats or threads
|
||||
* Creating or modifying channels
|
||||
* Creating or modifying meetings
|
||||
* Adding or removing participants
|
||||
* Changing memberships
|
||||
* Changing permissions
|
||||
* Modifying Teams settings
|
||||
* Any other operation that changes Microsoft Teams data
|
||||
|
||||
## Important Restrictions
|
||||
|
||||
* Never edit descriptions autonomously.
|
||||
* Never reply to comments autonomously.
|
||||
* Never send Teams messages autonomously.
|
||||
* Never open, close, resolve or reopen items autonomously.
|
||||
* Never change statuses autonomously.
|
||||
* Never trigger pipelines autonomously.
|
||||
* Never approve or merge pull requests autonomously.
|
||||
* Never perform destructive actions autonomously.
|
||||
|
||||
## Autonomous Agent Rule
|
||||
|
||||
The agent may freely:
|
||||
|
||||
* read
|
||||
* search
|
||||
* inspect
|
||||
* analyze
|
||||
* summarize
|
||||
|
||||
The agent must ask first before it:
|
||||
|
||||
* creates
|
||||
* edits
|
||||
* deletes
|
||||
* sends
|
||||
* comments
|
||||
* replies
|
||||
* reacts
|
||||
* assigns
|
||||
* changes state
|
||||
* opens
|
||||
* closes
|
||||
* approves
|
||||
* merges
|
||||
* triggers
|
||||
* cancels
|
||||
* modifies any remote data
|
||||
|
||||
When uncertain whether an operation is READ or WRITE, treat it as WRITE and ask first.
|
||||
@@ -0,0 +1,117 @@
|
||||
# Refactoring Guidelines
|
||||
|
||||
## Core Rule
|
||||
|
||||
* Refactor only when it improves readability, maintainability, correctness, performance, safety, or architecture.
|
||||
* Do not refactor unrelated code without a concrete reason.
|
||||
* Do not change behavior unless the refactoring explicitly requires it.
|
||||
* Preserve existing functionality by default.
|
||||
* Keep refactorings focused and minimal.
|
||||
* Prefer simple improvements over large rewrites.
|
||||
|
||||
## Scope
|
||||
|
||||
* Limit changes to the smallest reasonable scope.
|
||||
* Do not mix unrelated refactorings.
|
||||
* Do not combine feature work, bug fixes, formatting changes, and broad refactoring unless necessary.
|
||||
* Avoid repository-wide changes unless explicitly required.
|
||||
* Do not rename, move, split, or merge files unnecessarily.
|
||||
* Do not introduce new abstractions without a clear benefit.
|
||||
|
||||
## Behavior Preservation
|
||||
|
||||
* Existing public behavior must remain unchanged unless explicitly requested.
|
||||
* Preserve API contracts unless a breaking change is explicitly intended.
|
||||
* Preserve serialization formats, database contracts, configuration keys, routes, and external integrations unless explicitly required.
|
||||
* Preserve exception behavior where it is part of an existing contract.
|
||||
* Preserve thread-safety and concurrency behavior.
|
||||
* Preserve performance characteristics unless the refactoring intentionally improves them.
|
||||
|
||||
## Code Quality
|
||||
|
||||
* Prefer modern, readable C# syntax.
|
||||
* Reduce unnecessary complexity.
|
||||
* Remove duplication where doing so improves clarity.
|
||||
* Prefer clear control flow over clever code.
|
||||
* Reduce nesting where practical.
|
||||
* Improve naming when current names are misleading or unclear.
|
||||
* Prefer strongly typed code.
|
||||
* Avoid unnecessary interfaces and abstractions.
|
||||
* Avoid unnecessary wrapper classes and indirection.
|
||||
* Prefer composition over inheritance.
|
||||
* Remove dead code when it is clearly unused.
|
||||
* Remove obsolete comments and commented-out code.
|
||||
* Keep methods and classes focused.
|
||||
|
||||
## Architecture
|
||||
|
||||
* Respect existing architectural boundaries.
|
||||
* Do not introduce new layers without a concrete need.
|
||||
* Avoid circular dependencies.
|
||||
* Reduce coupling where practical.
|
||||
* Keep dependencies explicit.
|
||||
* Do not move business logic into infrastructure or presentation layers.
|
||||
* Do not weaken encapsulation for convenience.
|
||||
* Avoid global or static mutable state.
|
||||
|
||||
## Performance
|
||||
|
||||
* Do not trade significant readability for theoretical micro-optimizations.
|
||||
* Avoid introducing unnecessary allocations in hot paths.
|
||||
* Avoid unnecessary collection copies.
|
||||
* Avoid unnecessary LINQ in performance-critical code.
|
||||
* Preserve or improve algorithmic complexity.
|
||||
* Measure performance-sensitive refactorings when relevant.
|
||||
* Do not assume a refactoring is faster without evidence.
|
||||
|
||||
## Safety
|
||||
|
||||
* Do not weaken validation, authorization, authentication, encryption, null-safety, or input handling.
|
||||
* Preserve or improve error handling.
|
||||
* Preserve cancellation behavior.
|
||||
* Preserve disposal and resource lifetime semantics.
|
||||
* Avoid introducing race conditions.
|
||||
* Avoid exposing mutable internal state.
|
||||
* Treat external input as untrusted.
|
||||
* Do not introduce unsafe code unless explicitly required.
|
||||
|
||||
## Dependencies
|
||||
|
||||
* Do not add new dependencies unless they provide a clear and necessary benefit.
|
||||
* Prefer existing project dependencies and the .NET BCL.
|
||||
* Do not replace stable dependencies without a concrete reason.
|
||||
* Avoid refactorings that increase long-term maintenance cost.
|
||||
|
||||
## Tests
|
||||
|
||||
* Existing relevant tests must continue to pass.
|
||||
* Update tests when internal structure changes make it necessary.
|
||||
* Do not delete valid tests merely because they fail after a refactoring.
|
||||
* Add tests when the refactoring exposes previously untested critical behavior.
|
||||
* Prefer behavior-based tests over implementation-detail tests.
|
||||
|
||||
## Validation
|
||||
|
||||
After a refactoring:
|
||||
|
||||
* Build the affected project or solution.
|
||||
* Run relevant tests.
|
||||
* Check for new warnings.
|
||||
* Verify affected code paths.
|
||||
* Review the diff for accidental behavior changes.
|
||||
* Check that unrelated files were not modified unnecessarily.
|
||||
* Confirm that the result is simpler or clearer than before.
|
||||
|
||||
## Large Refactorings
|
||||
|
||||
* Break large refactorings into small, understandable steps.
|
||||
* Avoid big-bang rewrites when incremental changes are practical.
|
||||
* Keep intermediate states buildable where possible.
|
||||
* Do not perform broad architectural rewrites without explicit user intent.
|
||||
* If multiple valid architectural directions exist, ask the user before choosing one.
|
||||
|
||||
## Decision Rule
|
||||
|
||||
* If a refactoring may change externally visible behavior, data contracts, architecture, public APIs, persistence, security, or deployment behavior, ask the user first.
|
||||
* If the benefit is unclear or the change introduces significant complexity, do not proceed autonomously.
|
||||
* When uncertain, prefer the smaller and safer refactoring.
|
||||
@@ -0,0 +1,404 @@
|
||||
# Security Guidelines
|
||||
|
||||
Security is a default requirement for all code, architecture, configuration and infrastructure changes.
|
||||
|
||||
## Core Principles
|
||||
|
||||
* Prefer secure defaults.
|
||||
* Apply least privilege everywhere.
|
||||
* Minimize exposed attack surface.
|
||||
* Treat all external input as untrusted.
|
||||
* Never trust client-side validation alone.
|
||||
* Fail securely.
|
||||
* Prefer deny-by-default over allow-by-default for sensitive operations.
|
||||
* Keep security controls explicit and auditable.
|
||||
* Do not weaken security for convenience.
|
||||
* Do not bypass security mechanisms to make code easier to implement.
|
||||
* Do not introduce insecure temporary solutions.
|
||||
* Prefer simple, well-understood security mechanisms over custom cryptography or clever security logic.
|
||||
|
||||
## Secrets and Credentials
|
||||
|
||||
* Never hardcode passwords, API keys, tokens, connection strings, private keys or secrets.
|
||||
* Never commit secrets to source control.
|
||||
* Never log secrets or credentials.
|
||||
* Never expose secrets in exceptions, diagnostics or UI messages.
|
||||
* Use secure secret storage appropriate to the environment.
|
||||
* Prefer short-lived credentials where supported.
|
||||
* Rotate compromised credentials immediately.
|
||||
* Do not reuse credentials across environments.
|
||||
* Keep development, staging and production credentials separate.
|
||||
* Avoid secrets in URLs, query strings or command-line arguments.
|
||||
* Do not store secrets in frontend code.
|
||||
* Do not include real credentials in examples, tests or fixtures.
|
||||
|
||||
## Authentication
|
||||
|
||||
* Use established authentication standards and framework capabilities.
|
||||
* Do not implement custom authentication protocols without a strong reason.
|
||||
* Store passwords only using modern password hashing algorithms designed for password storage.
|
||||
* Never store plaintext passwords.
|
||||
* Never use reversible encryption for password storage.
|
||||
* Support secure session expiration.
|
||||
* Invalidate sessions or tokens when security-sensitive account state changes.
|
||||
* Protect authentication endpoints against brute-force abuse where applicable.
|
||||
* Avoid exposing whether an account exists unless required.
|
||||
* Require stronger authentication for security-sensitive actions where appropriate.
|
||||
|
||||
## Authorization
|
||||
|
||||
* Enforce authorization on the server side.
|
||||
* Never rely on hidden UI elements, disabled buttons or frontend guards as authorization.
|
||||
* Check authorization for every sensitive operation.
|
||||
* Prefer explicit permission checks.
|
||||
* Use least-privilege roles and permissions.
|
||||
* Avoid broad administrative permissions unless required.
|
||||
* Prevent horizontal privilege escalation between users or tenants.
|
||||
* Prevent vertical privilege escalation between permission levels.
|
||||
* Verify ownership of resources before access or modification.
|
||||
* Do not trust identifiers supplied by the client as proof of authorization.
|
||||
|
||||
## Input Validation
|
||||
|
||||
* Validate all input from users, APIs, files, databases, queues, environment variables and external systems.
|
||||
* Validate type, length, range, format and allowed values.
|
||||
* Prefer allowlists over denylists.
|
||||
* Reject unexpected input.
|
||||
* Normalize input before validation when appropriate.
|
||||
* Do not rely solely on client-side validation.
|
||||
* Validate identifiers before using them for resource access.
|
||||
* Validate uploaded files by content, size and expected type where applicable.
|
||||
* Do not trust file extensions alone.
|
||||
|
||||
## Injection Prevention
|
||||
|
||||
* Never concatenate untrusted input into SQL.
|
||||
* Use parameterized queries or ORM parameter binding.
|
||||
* Never concatenate untrusted input into shell commands.
|
||||
* Avoid executing shell commands when a direct API is available.
|
||||
* Validate and escape command arguments when process execution is required.
|
||||
* Prevent LDAP, XPath, template and expression injection where applicable.
|
||||
* Avoid dynamic code execution.
|
||||
* Avoid `eval`, dynamic compilation and equivalent mechanisms unless strictly required.
|
||||
* Treat template engines and interpreters as security boundaries.
|
||||
|
||||
## Web Security
|
||||
|
||||
* Prevent Cross-Site Scripting by using framework escaping and sanitization.
|
||||
* Never inject untrusted HTML directly.
|
||||
* Avoid bypassing framework sanitization.
|
||||
* Protect state-changing browser requests against CSRF where applicable.
|
||||
* Use secure cookies for sensitive session data.
|
||||
* Use `HttpOnly` for authentication cookies where possible.
|
||||
* Use `Secure` cookies in HTTPS environments.
|
||||
* Configure `SameSite` appropriately.
|
||||
* Use appropriate Content Security Policy where applicable.
|
||||
* Avoid leaking sensitive data through referrers or URLs.
|
||||
* Validate redirect targets to prevent open redirects.
|
||||
* Protect against clickjacking where applicable.
|
||||
|
||||
## API Security
|
||||
|
||||
* Authenticate sensitive endpoints.
|
||||
* Authorize every protected operation.
|
||||
* Validate all request payloads.
|
||||
* Apply reasonable request-size limits.
|
||||
* Apply pagination and bounded queries.
|
||||
* Apply rate limiting where abuse is possible.
|
||||
* Avoid exposing internal models directly when this leaks implementation details.
|
||||
* Return only data the caller is authorized to access.
|
||||
* Do not expose stack traces or internal exception details.
|
||||
* Avoid excessive information in error responses.
|
||||
* Version public APIs intentionally.
|
||||
* Protect administrative endpoints separately where appropriate.
|
||||
|
||||
## Data Protection
|
||||
|
||||
* Collect only data that is actually required.
|
||||
* Minimize storage of sensitive data.
|
||||
* Classify sensitive data explicitly.
|
||||
* Encrypt sensitive data in transit.
|
||||
* Encrypt sensitive data at rest where appropriate.
|
||||
* Do not implement custom encryption algorithms.
|
||||
* Use established cryptographic libraries.
|
||||
* Do not use obsolete cryptographic algorithms.
|
||||
* Do not use hardcoded encryption keys.
|
||||
* Use cryptographically secure random number generation for security-sensitive values.
|
||||
* Avoid exposing personal or sensitive data in logs.
|
||||
* Delete sensitive data when it is no longer required.
|
||||
|
||||
## Cryptography
|
||||
|
||||
* Never design custom cryptographic primitives.
|
||||
* Use current, established cryptographic standards.
|
||||
* Use authenticated encryption when confidentiality and integrity are required.
|
||||
* Verify signatures before trusting signed content.
|
||||
* Validate certificates correctly.
|
||||
* Never disable certificate validation.
|
||||
* Never accept all TLS certificates.
|
||||
* Do not downgrade TLS security.
|
||||
* Use secure randomness for tokens, nonces, identifiers and keys.
|
||||
* Never use predictable random generators for security-sensitive values.
|
||||
|
||||
## Tokens and Sessions
|
||||
|
||||
* Treat tokens as secrets.
|
||||
* Keep token lifetime as short as practical.
|
||||
* Validate issuer, audience, signature and expiration where applicable.
|
||||
* Do not accept unsigned tokens unless explicitly designed and safe.
|
||||
* Do not trust token contents before validation.
|
||||
* Avoid storing long-lived access tokens in insecure browser storage.
|
||||
* Rotate refresh tokens where appropriate.
|
||||
* Revoke compromised tokens where possible.
|
||||
* Prevent replay attacks where the protocol requires it.
|
||||
|
||||
## File Security
|
||||
|
||||
* Validate file names and paths.
|
||||
* Prevent path traversal.
|
||||
* Never concatenate untrusted input directly into filesystem paths.
|
||||
* Restrict file access to intended directories.
|
||||
* Use generated server-side file names where appropriate.
|
||||
* Enforce file size limits.
|
||||
* Validate uploaded content.
|
||||
* Do not execute uploaded files.
|
||||
* Store uploads outside executable web roots where applicable.
|
||||
* Handle archive extraction safely.
|
||||
* Prevent zip-slip and equivalent path traversal attacks.
|
||||
* Avoid following untrusted symbolic links where security-sensitive.
|
||||
|
||||
## Serialization
|
||||
|
||||
* Treat deserialized input as untrusted.
|
||||
* Avoid insecure polymorphic deserialization.
|
||||
* Avoid deserializing arbitrary runtime types.
|
||||
* Use explicit schemas or known DTOs.
|
||||
* Restrict type resolution.
|
||||
* Do not deserialize executable objects or behavior.
|
||||
* Validate deserialized data before use.
|
||||
* Avoid insecure legacy serializers.
|
||||
|
||||
## Database Security
|
||||
|
||||
* Use parameterized queries.
|
||||
* Use least-privilege database accounts.
|
||||
* Do not use administrative database accounts for normal application traffic.
|
||||
* Restrict schema modification permissions in runtime accounts.
|
||||
* Protect connection strings.
|
||||
* Avoid exposing raw database errors.
|
||||
* Limit query size and result sets.
|
||||
* Prevent tenant data leakage.
|
||||
* Verify tenant boundaries in every relevant query.
|
||||
* Use transactions where integrity requires atomicity.
|
||||
|
||||
## Logging and Monitoring
|
||||
|
||||
* Never log secrets.
|
||||
* Never log passwords.
|
||||
* Never log authentication tokens.
|
||||
* Avoid logging sensitive personal data.
|
||||
* Use structured logging.
|
||||
* Include security-relevant context without exposing sensitive values.
|
||||
* Log authentication and authorization failures where appropriate.
|
||||
* Log suspicious or high-risk actions where appropriate.
|
||||
* Avoid log injection by treating user input as data.
|
||||
* Do not let logging failures break critical application behavior.
|
||||
* Ensure logs have appropriate access controls.
|
||||
|
||||
## Error Handling
|
||||
|
||||
* Fail securely.
|
||||
* Do not expose internal stack traces to users.
|
||||
* Do not reveal implementation details unnecessarily.
|
||||
* Preserve diagnostic detail internally where safe.
|
||||
* Avoid different error responses that reveal sensitive existence checks where not required.
|
||||
* Do not swallow security-relevant exceptions.
|
||||
* Do not continue execution after critical validation or authorization failures.
|
||||
|
||||
## Dependencies
|
||||
|
||||
* Keep dependencies minimal.
|
||||
* Prefer maintained and widely used packages.
|
||||
* Avoid abandoned packages.
|
||||
* Avoid unnecessary dependencies for trivial functionality.
|
||||
* Keep dependencies updated with security patches.
|
||||
* Review dependency changes before adoption.
|
||||
* Do not blindly update major versions without compatibility review.
|
||||
* Remove unused dependencies.
|
||||
* Treat transitive dependencies as part of the attack surface.
|
||||
* Verify package identity before installation.
|
||||
* Avoid untrusted package sources.
|
||||
* Respect lockfiles.
|
||||
|
||||
## Supply Chain Security
|
||||
|
||||
* Pin dependency versions where appropriate.
|
||||
* Protect build and deployment pipelines.
|
||||
* Do not expose CI/CD credentials.
|
||||
* Use least privilege for pipeline identities.
|
||||
* Review third-party actions, plugins and build scripts.
|
||||
* Avoid executing untrusted build scripts.
|
||||
* Verify artifacts and sources where practical.
|
||||
* Keep generated artifacts traceable to source.
|
||||
* Do not publish secrets in build logs or artifacts.
|
||||
|
||||
## Configuration
|
||||
|
||||
* Use secure production defaults.
|
||||
* Do not enable debug mode in production.
|
||||
* Do not expose development endpoints in production.
|
||||
* Separate environment-specific configuration.
|
||||
* Validate security-sensitive configuration at startup.
|
||||
* Fail startup when mandatory security configuration is missing.
|
||||
* Do not silently fall back to insecure settings.
|
||||
* Protect configuration files containing sensitive values.
|
||||
|
||||
## Network Security
|
||||
|
||||
* Use HTTPS for sensitive or authenticated communication.
|
||||
* Do not disable TLS validation.
|
||||
* Restrict outbound network access where practical.
|
||||
* Restrict inbound services to required ports and interfaces.
|
||||
* Use timeouts for network operations.
|
||||
* Limit retries to avoid amplification or denial-of-service behavior.
|
||||
* Validate remote endpoints where SSRF is possible.
|
||||
* Do not allow arbitrary user-controlled URLs for privileged server-side requests.
|
||||
* Block access to internal network ranges when handling untrusted remote URLs where applicable.
|
||||
|
||||
## SSRF Prevention
|
||||
|
||||
* Treat user-controlled URLs as dangerous.
|
||||
* Validate schemes.
|
||||
* Prefer allowlisted hosts.
|
||||
* Resolve and verify target addresses where necessary.
|
||||
* Prevent access to localhost, metadata endpoints and internal networks where not explicitly required.
|
||||
* Revalidate after redirects.
|
||||
* Limit redirects.
|
||||
* Apply request timeouts and response-size limits.
|
||||
|
||||
## Concurrency and Resource Abuse
|
||||
|
||||
* Bound concurrency.
|
||||
* Avoid unbounded task creation.
|
||||
* Avoid unbounded queues.
|
||||
* Limit request sizes.
|
||||
* Limit collection sizes when processing external input.
|
||||
* Apply timeouts to external operations.
|
||||
* Apply cancellation where practical.
|
||||
* Prevent expensive operations from being triggered repeatedly without limits.
|
||||
* Protect endpoints against denial-of-service through algorithmic complexity.
|
||||
* Avoid user-controlled regular expressions that may cause catastrophic backtracking.
|
||||
|
||||
## Memory Safety and Resource Management
|
||||
|
||||
* Dispose files, streams, sockets and other resources correctly.
|
||||
* Prevent resource leaks.
|
||||
* Avoid retaining sensitive data in memory longer than necessary.
|
||||
* Avoid unsafe code unless explicitly required.
|
||||
* Review pointer and memory operations carefully.
|
||||
* Avoid exposing raw memory or buffers across trust boundaries.
|
||||
* Clear sensitive buffers where warranted.
|
||||
|
||||
## Multi-Tenant Systems
|
||||
|
||||
* Treat tenant boundaries as security boundaries.
|
||||
* Scope every tenant-owned query explicitly.
|
||||
* Never trust tenant identifiers from the client without authorization.
|
||||
* Prevent cross-tenant cache leakage.
|
||||
* Prevent cross-tenant logging or diagnostics leakage.
|
||||
* Keep tenant-specific secrets isolated.
|
||||
* Test horizontal privilege escalation explicitly.
|
||||
|
||||
## Frontend Security
|
||||
|
||||
* Assume frontend code and data are visible to the user.
|
||||
* Never embed secrets in frontend applications.
|
||||
* Never rely on frontend checks for authorization.
|
||||
* Treat browser storage as potentially accessible to malicious scripts.
|
||||
* Avoid storing sensitive long-lived tokens unnecessarily.
|
||||
* Escape or sanitize untrusted content.
|
||||
* Do not bypass framework security controls without explicit justification.
|
||||
|
||||
## Desktop Application Security
|
||||
|
||||
* Treat local files and IPC input as untrusted where applicable.
|
||||
* Do not assume local users or processes are trusted.
|
||||
* Avoid storing secrets in plaintext configuration.
|
||||
* Protect locally cached sensitive data.
|
||||
* Validate update packages and downloaded executables.
|
||||
* Do not execute arbitrary files or commands from untrusted input.
|
||||
* Use least privilege and avoid unnecessary elevation.
|
||||
|
||||
## Security-Sensitive Changes
|
||||
|
||||
Changes affecting any of the following require additional scrutiny:
|
||||
|
||||
* Authentication
|
||||
* Authorization
|
||||
* Cryptography
|
||||
* Secrets
|
||||
* User permissions
|
||||
* File access
|
||||
* Process execution
|
||||
* Network access
|
||||
* Input validation
|
||||
* Serialization
|
||||
* Database access
|
||||
* Payment or financial data
|
||||
* Personal or confidential data
|
||||
* Admin functionality
|
||||
* Deployment or infrastructure security
|
||||
|
||||
For security-sensitive changes:
|
||||
|
||||
* Prefer established framework functionality.
|
||||
* Review trust boundaries.
|
||||
* Review failure behavior.
|
||||
* Review privilege requirements.
|
||||
* Review input validation.
|
||||
* Review logging for data leakage.
|
||||
* Review backward compatibility for security implications.
|
||||
* Add or update relevant security tests.
|
||||
|
||||
## Security Testing
|
||||
|
||||
* Test authorization failures.
|
||||
* Test invalid and malicious input.
|
||||
* Test boundary values.
|
||||
* Test unauthenticated access.
|
||||
* Test unauthorized resource access.
|
||||
* Test cross-user and cross-tenant access where applicable.
|
||||
* Test expired and invalid credentials.
|
||||
* Test malformed payloads.
|
||||
* Test path traversal where files are involved.
|
||||
* Test injection risks where interpreters or databases are involved.
|
||||
* Test rate and resource limits where abuse is realistic.
|
||||
* Preserve regression tests for discovered security issues.
|
||||
|
||||
## Agent Rules
|
||||
|
||||
* Never intentionally weaken security controls without explicit user instruction.
|
||||
* Never disable certificate validation, authentication, authorization, validation or security middleware to solve a problem.
|
||||
* Never add hardcoded secrets.
|
||||
* Never expose sensitive data for debugging convenience.
|
||||
* Never bypass a security check because it blocks implementation.
|
||||
* Never assume trusted input without a clearly defined trust boundary.
|
||||
* Never silently choose a less secure implementation because it is easier.
|
||||
* If a requested change creates a meaningful security risk, clearly identify the risk before proceeding.
|
||||
* If requirements are ambiguous in a security-sensitive area, ask the user instead of making an autonomous security decision.
|
||||
|
||||
## Priority Order
|
||||
|
||||
Prioritize security decisions in this order:
|
||||
|
||||
* Prevent unauthorized access
|
||||
* Protect sensitive data
|
||||
* Preserve integrity
|
||||
* Minimize privileges
|
||||
* Minimize attack surface
|
||||
* Validate trust boundaries
|
||||
* Maintain availability
|
||||
* Preserve auditability
|
||||
* Optimize usability and performance only within acceptable security constraints
|
||||
|
||||
Security must not be traded away for convenience without an explicit and informed decision.
|
||||
@@ -0,0 +1,160 @@
|
||||
# TypeScript Code Guidelines
|
||||
|
||||
* Write clear, readable, maintainable code first.
|
||||
* Prefer modern TypeScript and current ECMAScript syntax.
|
||||
* Keep code simple and explicit.
|
||||
* Avoid clever or overly abstract solutions.
|
||||
* Follow the existing project style and architecture.
|
||||
* Enable strict TypeScript settings where possible.
|
||||
* Prefer `strict: true`.
|
||||
* Avoid `any`.
|
||||
* Prefer precise types over broad types.
|
||||
* Prefer `unknown` over `any` for untrusted or unknown values.
|
||||
* Narrow types explicitly before use.
|
||||
* Prefer strongly typed models over loose objects.
|
||||
* Avoid excessive type assertions.
|
||||
* Avoid non-null assertions unless safety is guaranteed.
|
||||
* Prefer discriminated unions for state and variant modeling.
|
||||
* Prefer literal unions over arbitrary strings.
|
||||
* Prefer enums only when they provide a clear benefit.
|
||||
* Prefer `readonly` where mutation is not required.
|
||||
* Prefer immutable data where practical.
|
||||
* Avoid unnecessary mutation.
|
||||
* Avoid global mutable state.
|
||||
* Keep functions small and focused.
|
||||
* Keep modules focused on a clear responsibility.
|
||||
* Prefer composition over inheritance.
|
||||
* Avoid unnecessary classes when functions and plain objects are sufficient.
|
||||
* Avoid unnecessary interfaces and abstractions.
|
||||
* Prefer concrete object types when no abstraction is required.
|
||||
* Use interfaces primarily when extension, implementation contracts, or declaration merging is actually useful.
|
||||
* Prefer `type` aliases for unions, compositions, mapped types, and local data models.
|
||||
* Avoid unnecessary wrapper types.
|
||||
* Avoid excessive generic complexity.
|
||||
* Keep generic constraints explicit and meaningful.
|
||||
* Avoid deeply nested conditional or mapped types unless they provide clear value.
|
||||
* Prefer readable types over type-system cleverness.
|
||||
* Avoid duplicated type definitions.
|
||||
* Derive types from existing sources when practical.
|
||||
* Do not duplicate backend contracts manually when generated or shared types are available.
|
||||
* Prefer explicit return types for public APIs and non-trivial functions.
|
||||
* Prefer inference for simple local variables.
|
||||
* Avoid unnecessary annotations when inference is obvious.
|
||||
* Prefer `const` by default.
|
||||
* Use `let` only when reassignment is required.
|
||||
* Avoid `var`.
|
||||
* Prefer optional chaining and nullish coalescing where appropriate.
|
||||
* Do not use `||` when `0`, `false`, or empty strings are valid values.
|
||||
* Handle `null` and `undefined` intentionally.
|
||||
* Avoid mixing `null` and `undefined` without a clear convention.
|
||||
* Prefer early returns over excessive nesting.
|
||||
* Avoid deeply nested control flow.
|
||||
* Avoid overly large functions.
|
||||
* Avoid hidden side effects.
|
||||
* Keep pure logic pure where practical.
|
||||
* Prefer deterministic behavior.
|
||||
* Avoid implicit runtime coercion.
|
||||
* Use strict equality.
|
||||
* Avoid unnecessary object spreading in hot paths.
|
||||
* Avoid unnecessary array copies.
|
||||
* Avoid unnecessary intermediate arrays.
|
||||
* Avoid repeated `.map()`, `.filter()`, or `.reduce()` chains in performance-critical paths.
|
||||
* Use array methods when they improve readability and performance is not critical.
|
||||
* Prefer appropriate data structures such as `Map` and `Set` when lookup behavior requires them.
|
||||
* Avoid O(n²) patterns when a better structure is practical.
|
||||
* Measure performance before micro-optimizing.
|
||||
* Avoid unnecessary JSON serialization and parsing.
|
||||
* Avoid unnecessary deep cloning.
|
||||
* Avoid `JSON.parse(JSON.stringify(...))` as a cloning strategy.
|
||||
* Prefer platform APIs such as `structuredClone` when deep cloning is actually required.
|
||||
* Avoid synchronous blocking operations in server-side hot paths.
|
||||
* Prefer asynchronous APIs for I/O.
|
||||
* Always handle rejected promises.
|
||||
* Avoid floating promises.
|
||||
* Use `await` when sequencing is required.
|
||||
* Use `Promise.all` for independent operations when safe.
|
||||
* Limit concurrency for large workloads.
|
||||
* Avoid uncontrolled `Promise.all` over very large collections.
|
||||
* Support cancellation with `AbortSignal` where applicable.
|
||||
* Clean up event listeners, timers, subscriptions, streams, and resources.
|
||||
* Avoid memory leaks caused by retained closures or listeners.
|
||||
* Do not swallow exceptions.
|
||||
* Preserve useful error context.
|
||||
* Use typed domain errors where they improve handling.
|
||||
* Avoid exceptions for normal control flow.
|
||||
* Validate external input at system boundaries.
|
||||
* Never trust API payloads, query parameters, environment variables, storage data, or user input based solely on TypeScript types.
|
||||
* Use runtime validation for untrusted external data.
|
||||
* Do not assume compile-time types provide runtime safety.
|
||||
* Prefer schema validation when external contracts are complex.
|
||||
* Never expose secrets, tokens, credentials, or sensitive data.
|
||||
* Do not log sensitive information.
|
||||
* Avoid unsafe dynamic property access.
|
||||
* Avoid `eval`, `Function`, and dynamic code execution.
|
||||
* Avoid unsafe HTML injection.
|
||||
* Sanitize untrusted HTML when rendering HTML is required.
|
||||
* Avoid weakening TLS, authentication, authorization, CSP, validation, or other security controls.
|
||||
* Treat all external data as untrusted.
|
||||
* Prefer secure defaults.
|
||||
* Do not disable security checks for convenience.
|
||||
* Avoid prototype pollution risks when merging untrusted objects.
|
||||
* Prefer allowlists over denylists for security-sensitive validation.
|
||||
* Keep dependencies minimal.
|
||||
* Prefer built-in platform APIs over adding small utility dependencies.
|
||||
* Do not add dependencies without a clear reason.
|
||||
* Avoid abandoned or unnecessary packages.
|
||||
* Keep dependencies current and supported.
|
||||
* Respect lockfiles.
|
||||
* Do not manually modify generated lockfile content.
|
||||
* Avoid broad dependency upgrades unrelated to the task.
|
||||
* Use ESM or the project's existing module system consistently.
|
||||
* Avoid mixing module systems without necessity.
|
||||
* Prefer named exports unless the project convention favors default exports.
|
||||
* Keep import paths consistent.
|
||||
* Remove unused imports and exports.
|
||||
* Avoid circular dependencies.
|
||||
* Keep frontend, domain, application, and infrastructure concerns separated where applicable.
|
||||
* Keep API and transport models separate from domain logic when necessary.
|
||||
* Do not leak implementation details through public APIs.
|
||||
* Avoid unnecessary public exports.
|
||||
* Keep module boundaries intentional.
|
||||
* Write code that is easy to test.
|
||||
* Prefer behavior-based tests.
|
||||
* Avoid tests coupled to implementation details.
|
||||
* Mock only external boundaries or expensive dependencies where practical.
|
||||
* Keep tests deterministic.
|
||||
* Avoid time-, network-, and environment-dependent tests without proper isolation.
|
||||
* Remove dead code instead of keeping it as commented-out code.
|
||||
* Do not add comments unless the user explicitly requests them.
|
||||
* Use descriptive naming.
|
||||
* Avoid vague names such as `data`, `obj`, `item`, `temp`, or `value` when more precise names are available.
|
||||
* Avoid abbreviations unless they are established domain terminology.
|
||||
* Keep naming conventions consistent.
|
||||
* Treat lint and TypeScript errors seriously.
|
||||
* Do not suppress ESLint or TypeScript diagnostics without a concrete reason.
|
||||
* Avoid `@ts-ignore`.
|
||||
* Prefer `@ts-expect-error` only when the error is intentional and documented.
|
||||
* Do not disable lint rules globally for local problems.
|
||||
* Prefer correctness, security, maintainability, and predictable behavior over micro-optimizations.
|
||||
|
||||
## Performance Priority
|
||||
|
||||
Prioritize performance work in this order:
|
||||
|
||||
* Architecture
|
||||
* Network and API usage
|
||||
* Database access
|
||||
* Algorithms and data structures
|
||||
* Rendering and state updates
|
||||
* Concurrency
|
||||
* Memory allocations
|
||||
* CPU micro-optimizations
|
||||
|
||||
Never optimize based purely on assumptions.
|
||||
|
||||
## Safety Rule
|
||||
|
||||
* Compile-time type safety is not runtime validation.
|
||||
* Validate all external and untrusted data.
|
||||
* Do not use `any`, type assertions, non-null assertions, or disabled compiler checks to bypass real type problems.
|
||||
* Prefer making invalid states unrepresentable where practical.
|
||||
@@ -0,0 +1,306 @@
|
||||
# UI & UX Guidelines
|
||||
|
||||
* Design for clarity first.
|
||||
* Prefer simple, modern and predictable interfaces.
|
||||
* Optimize for fast understanding and low cognitive load.
|
||||
* Every screen should have a clear primary purpose.
|
||||
* Every important action should be easy to discover.
|
||||
* Prefer familiar interaction patterns over novel ones.
|
||||
* Do not require users to learn unnecessary custom behavior.
|
||||
* Keep layouts visually calm and structured.
|
||||
* Use consistent spacing, typography, colors and interaction patterns.
|
||||
* Avoid visual noise.
|
||||
* Avoid decorative elements that do not improve usability.
|
||||
* Avoid unnecessary complexity in navigation and workflows.
|
||||
* Minimize the number of steps required to complete common tasks.
|
||||
* Keep related information and actions close together.
|
||||
* Group content logically.
|
||||
* Use clear visual hierarchy.
|
||||
* Make primary actions visually distinct from secondary actions.
|
||||
* Avoid giving multiple actions equal visual priority when one is clearly more important.
|
||||
* Use whitespace intentionally.
|
||||
* Prefer readable line lengths and sufficient spacing.
|
||||
* Avoid dense walls of content.
|
||||
* Avoid oversized empty areas that reduce information efficiency.
|
||||
* Keep important information visible without unnecessary scrolling where practical.
|
||||
|
||||
## Navigation
|
||||
|
||||
* Navigation must be predictable and consistent.
|
||||
* Users should always understand where they are.
|
||||
* Users should always understand how to go back.
|
||||
* Avoid hidden navigation when visible navigation is practical.
|
||||
* Keep navigation depth shallow where possible.
|
||||
* Use clear and descriptive navigation labels.
|
||||
* Do not use ambiguous icons without labels when meaning is not obvious.
|
||||
* Preserve navigation state when users return to a previous view where practical.
|
||||
* Avoid resetting filters, search state or scroll position unnecessarily.
|
||||
* Avoid unexpected redirects.
|
||||
* Do not change navigation behavior between similar screens without a clear reason.
|
||||
|
||||
## Actions
|
||||
|
||||
* Use clear action labels.
|
||||
* Prefer verbs that describe the actual outcome.
|
||||
* Avoid vague labels such as `OK`, `Submit`, `Proceed` or `Execute` when a more specific label is possible.
|
||||
* Make destructive actions clearly distinguishable.
|
||||
* Keep dangerous actions away from common actions.
|
||||
* Require confirmation for destructive or difficult-to-reverse actions.
|
||||
* Do not require unnecessary confirmation for safe, reversible actions.
|
||||
* Disable unavailable actions when the reason is obvious.
|
||||
* Explain why an action is unavailable when it is not obvious.
|
||||
* Avoid actions that appear clickable but are not.
|
||||
* Provide immediate visual feedback after user actions.
|
||||
* Prevent accidental duplicate submissions.
|
||||
* Make loading, success and failure states visible.
|
||||
|
||||
## Forms
|
||||
|
||||
* Keep forms as short as practical.
|
||||
* Ask only for information that is actually required.
|
||||
* Group related fields together.
|
||||
* Use clear field labels.
|
||||
* Do not rely on placeholders as the only label.
|
||||
* Use appropriate input controls for the expected value.
|
||||
* Provide useful defaults where safe and predictable.
|
||||
* Preserve user input when validation or network errors occur.
|
||||
* Validate fields at useful moments without interrupting normal input.
|
||||
* Show validation errors close to the affected field.
|
||||
* Explain how to fix invalid input.
|
||||
* Avoid technical validation messages.
|
||||
* Clearly mark optional fields where useful.
|
||||
* Avoid asking the same information multiple times.
|
||||
* Use autocomplete and autofill where appropriate.
|
||||
* Make keyboard navigation logical.
|
||||
* Use sensible tab order.
|
||||
* Support Enter and Escape behavior where users expect it.
|
||||
|
||||
## Content and Language
|
||||
|
||||
* Use plain, concise language.
|
||||
* Prefer user terminology over internal technical terminology.
|
||||
* Avoid jargon unless the target users are expected to understand it.
|
||||
* Use consistent naming for the same concepts.
|
||||
* Do not rename concepts between screens.
|
||||
* Keep button labels, headings and descriptions concise.
|
||||
* Put the most important information first.
|
||||
* Avoid unnecessary explanatory text.
|
||||
* Add explanation only where users may reasonably be confused.
|
||||
* Error messages should explain what happened and what the user can do next.
|
||||
* Avoid blaming the user.
|
||||
* Avoid exposing stack traces, exception names or internal implementation details.
|
||||
|
||||
## Feedback and System State
|
||||
|
||||
* Always communicate important system state.
|
||||
* Show loading states for operations that are not immediate.
|
||||
* Avoid indefinite loading indicators without context.
|
||||
* Use progress indicators for longer operations where progress can be measured.
|
||||
* Clearly distinguish loading, empty, error and success states.
|
||||
* Do not leave blank screens where an empty state is expected.
|
||||
* Empty states should explain what the user can do next.
|
||||
* Show success feedback when the result is not otherwise obvious.
|
||||
* Keep transient notifications concise.
|
||||
* Do not hide important errors in temporary notifications.
|
||||
* Preserve actionable errors until the user has had a chance to understand them.
|
||||
* Do not silently fail.
|
||||
* Do not silently discard user input.
|
||||
|
||||
## Responsiveness
|
||||
|
||||
* The interface should feel responsive at all times.
|
||||
* Provide immediate feedback after interaction.
|
||||
* Avoid blocking the entire interface when only one section is loading.
|
||||
* Prefer localized loading states.
|
||||
* Use optimistic UI only when failures can be handled safely.
|
||||
* Avoid layout jumps during loading.
|
||||
* Reserve space for content where practical.
|
||||
* Keep animations short and functional.
|
||||
* Do not use animations that delay task completion.
|
||||
* Respect reduced-motion preferences.
|
||||
* Avoid unnecessary transitions and visual effects.
|
||||
|
||||
## Visual Design
|
||||
|
||||
* Prefer modern, clean and restrained visual design.
|
||||
* Use a consistent design system.
|
||||
* Keep typography hierarchy clear.
|
||||
* Maintain sufficient contrast.
|
||||
* Use color intentionally.
|
||||
* Do not rely on color alone to communicate state.
|
||||
* Keep the number of accent colors limited.
|
||||
* Avoid excessive gradients, shadows and decorative effects.
|
||||
* Use rounded corners, borders and elevation consistently.
|
||||
* Keep icons stylistically consistent.
|
||||
* Use familiar icons for familiar actions.
|
||||
* Pair unclear icons with text labels.
|
||||
* Avoid tiny click targets.
|
||||
* Keep interactive targets large enough for comfortable use.
|
||||
* Maintain consistent alignment.
|
||||
* Avoid arbitrary spacing values.
|
||||
* Prefer reusable spacing and sizing tokens.
|
||||
|
||||
## Accessibility
|
||||
|
||||
* Accessibility is part of the default design, not an optional enhancement.
|
||||
* Use semantic controls and elements.
|
||||
* Ensure full keyboard usability.
|
||||
* Maintain visible focus indicators.
|
||||
* Use sufficient color contrast.
|
||||
* Do not rely solely on hover interactions.
|
||||
* Do not rely solely on color to indicate status.
|
||||
* Provide accessible names for controls.
|
||||
* Keep focus order logical.
|
||||
* Move focus intentionally after dialogs, navigation or major state changes.
|
||||
* Support screen readers where applicable.
|
||||
* Use ARIA only when native semantics are insufficient.
|
||||
* Respect reduced-motion and system accessibility preferences.
|
||||
* Avoid flashing or distracting content.
|
||||
|
||||
## Responsive Design
|
||||
|
||||
* Design for the available viewport instead of fixed screen sizes.
|
||||
* Prioritize important content on smaller screens.
|
||||
* Avoid horizontal scrolling unless the content genuinely requires it.
|
||||
* Keep controls usable on touch devices.
|
||||
* Do not simply shrink desktop layouts.
|
||||
* Adapt navigation and layout intentionally for smaller screens.
|
||||
* Preserve core functionality across supported screen sizes.
|
||||
* Avoid hiding important actions solely because space is limited.
|
||||
* Test common breakpoints and extreme content lengths.
|
||||
|
||||
## Tables and Data-Dense Views
|
||||
|
||||
* Use tables only for genuinely tabular data.
|
||||
* Keep column names concise.
|
||||
* Align numeric data consistently.
|
||||
* Make sorting and filtering discoverable.
|
||||
* Preserve filter and sort state where useful.
|
||||
* Do not overload tables with too many actions.
|
||||
* Prefer a clear primary row action and secondary contextual actions.
|
||||
* Keep important columns visible.
|
||||
* Allow horizontal scrolling only when necessary.
|
||||
* Use pagination, virtualization or incremental loading for large data sets.
|
||||
* Provide clear empty states.
|
||||
* Avoid showing unnecessary columns by default.
|
||||
* Use sensible formatting for dates, numbers and units.
|
||||
|
||||
## Search and Filtering
|
||||
|
||||
* Search should behave predictably.
|
||||
* Make active filters visible.
|
||||
* Make filters easy to remove.
|
||||
* Provide a clear way to reset filters.
|
||||
* Preserve search and filter state when navigating back where practical.
|
||||
* Avoid requiring users to configure many filters before seeing results.
|
||||
* Use sensible defaults.
|
||||
* Clearly distinguish no results from loading or errors.
|
||||
* Suggest recovery options when no results are found.
|
||||
|
||||
## Dialogs and Modals
|
||||
|
||||
* Use dialogs only when interruption is justified.
|
||||
* Avoid stacking dialogs.
|
||||
* Keep dialogs focused on one decision or task.
|
||||
* Use clear titles.
|
||||
* Keep primary and secondary actions obvious.
|
||||
* Make cancellation easy.
|
||||
* Support Escape where appropriate.
|
||||
* Do not use dialogs for information that belongs inline.
|
||||
* Avoid large workflows inside modal dialogs.
|
||||
* Do not close dialogs unexpectedly while users are entering data.
|
||||
|
||||
## Destructive Actions
|
||||
|
||||
* Clearly label destructive actions.
|
||||
* Use confirmations for irreversible or high-impact operations.
|
||||
* Explain the consequence before confirmation.
|
||||
* Prefer reversible actions when possible.
|
||||
* Offer undo where practical.
|
||||
* Do not use generic confirmation text for destructive operations.
|
||||
* Make the safe action visually distinct.
|
||||
* Do not preselect destructive choices.
|
||||
|
||||
## Error Prevention
|
||||
|
||||
* Prevent invalid actions before they occur where practical.
|
||||
* Use constraints and suitable controls instead of relying only on validation errors.
|
||||
* Provide sensible defaults.
|
||||
* Confirm only high-impact decisions.
|
||||
* Warn users before losing unsaved changes.
|
||||
* Do not clear entered data unexpectedly.
|
||||
* Avoid ambiguous state transitions.
|
||||
* Make dependencies between fields or actions visible.
|
||||
|
||||
## Consistency
|
||||
|
||||
* Similar problems should have similar UI solutions.
|
||||
* Similar actions should use the same wording and placement.
|
||||
* Do not introduce custom patterns when an existing pattern already solves the problem.
|
||||
* Reuse components and design tokens.
|
||||
* Keep interaction behavior consistent across the application.
|
||||
* Preserve platform conventions unless there is a strong reason not to.
|
||||
|
||||
## User Control
|
||||
|
||||
* Keep users in control of important actions.
|
||||
* Do not perform surprising destructive actions automatically.
|
||||
* Do not change user data without a clear action or established behavior.
|
||||
* Make automatic behavior visible when it materially affects the user.
|
||||
* Allow users to cancel long-running operations where practical.
|
||||
* Allow recovery from mistakes where possible.
|
||||
* Avoid dark patterns.
|
||||
* Never manipulate users into actions they did not intend.
|
||||
|
||||
## Progressive Disclosure
|
||||
|
||||
* Show the most important options first.
|
||||
* Hide advanced complexity until it is needed.
|
||||
* Do not overwhelm users with every possible setting at once.
|
||||
* Keep advanced options discoverable.
|
||||
* Avoid forcing expert workflows on normal users.
|
||||
* Avoid hiding frequently used functionality behind excessive menus.
|
||||
|
||||
## Performance Perception
|
||||
|
||||
* Optimize perceived performance as well as actual performance.
|
||||
* Show useful content as early as possible.
|
||||
* Avoid blocking initial rendering on non-critical data.
|
||||
* Use skeletons only when they improve comprehension.
|
||||
* Avoid fake progress.
|
||||
* Do not use loading animations to mask avoidable slowness.
|
||||
* Keep interactions responsive even while background work continues.
|
||||
|
||||
## Defaults
|
||||
|
||||
* Choose safe and sensible defaults.
|
||||
* Defaults should match the most common expected user intent.
|
||||
* Avoid defaults with destructive consequences.
|
||||
* Preserve user preferences when appropriate.
|
||||
* Do not force repeated configuration for common workflows.
|
||||
|
||||
## Design Decision Rule
|
||||
|
||||
* Every UI element should have a clear purpose.
|
||||
* Every additional interaction adds cognitive cost.
|
||||
* Prefer removing complexity over explaining unnecessary complexity.
|
||||
* Prefer familiar patterns over clever ones.
|
||||
* Prefer fewer clear choices over many ambiguous choices.
|
||||
* Prefer predictable behavior over surprising automation.
|
||||
* If a design decision introduces ambiguity, unnecessary complexity, or multiple equally valid UX directions, ask the user instead of deciding autonomously.
|
||||
|
||||
## Priority Order
|
||||
|
||||
Prioritize UI/UX decisions in this order:
|
||||
|
||||
* Correctness
|
||||
* Clarity
|
||||
* Safety
|
||||
* Accessibility
|
||||
* User control
|
||||
* Task efficiency
|
||||
* Consistency
|
||||
* Responsiveness
|
||||
* Visual polish
|
||||
|
||||
Visual polish must never reduce usability.
|
||||
@@ -0,0 +1,375 @@
|
||||
# WPF Code Guidelines
|
||||
|
||||
* Use modern C# and current .NET/WPF conventions.
|
||||
* Keep UI, application logic and domain logic clearly separated.
|
||||
* Prefer MVVM for non-trivial views.
|
||||
* Keep code-behind minimal.
|
||||
* Use code-behind only for view-specific behavior that does not belong in the ViewModel.
|
||||
* Avoid business logic in views.
|
||||
* Avoid direct service access from controls.
|
||||
* Keep dependencies explicit and testable.
|
||||
* Prefer composition over inheritance.
|
||||
* Avoid unnecessary abstractions and framework wrappers.
|
||||
* Follow the existing project architecture unless there is a strong reason to change it.
|
||||
|
||||
## MVVM
|
||||
|
||||
* Keep ViewModels focused on presentation state and commands.
|
||||
* Do not put UI element references into ViewModels.
|
||||
* Do not access `Window`, `UserControl`, `DispatcherObject` or visual tree elements from ViewModels.
|
||||
* Avoid direct navigation, dialogs or message boxes from ViewModels without an abstraction when testability matters.
|
||||
* Prefer explicit application services for navigation, dialogs and external interactions.
|
||||
* Keep domain logic outside ViewModels.
|
||||
* Do not use ViewModels as general-purpose service containers.
|
||||
* Keep ViewModel dependencies minimal.
|
||||
* Prefer immutable or readonly state where practical.
|
||||
* Avoid duplicated derived state.
|
||||
* Keep state transitions predictable.
|
||||
|
||||
## Data Binding
|
||||
|
||||
* Prefer data binding over manual UI synchronization.
|
||||
* Use strongly typed properties.
|
||||
* Use appropriate binding modes.
|
||||
* Prefer `OneWay` when two-way updates are not required.
|
||||
* Use `TwoWay` only when the UI must modify the source.
|
||||
* Avoid unnecessary `UpdateSourceTrigger=PropertyChanged` for expensive operations.
|
||||
* Keep binding paths simple and stable.
|
||||
* Avoid deeply nested binding paths.
|
||||
* Do not hide broken bindings.
|
||||
* Treat binding errors as real defects.
|
||||
* Use `FallbackValue` and `TargetNullValue` only when they reflect intended behavior.
|
||||
* Avoid excessive converters.
|
||||
* Prefer exposing correctly shaped state from the ViewModel over complex converter logic.
|
||||
* Avoid `MultiBinding` when simpler state modeling is clearer.
|
||||
* Do not put business logic into converters.
|
||||
|
||||
## Property Change Notifications
|
||||
|
||||
* Implement property change notifications consistently.
|
||||
* Avoid raising `PropertyChanged` unnecessarily.
|
||||
* Raise notifications only when values actually change.
|
||||
* Keep dependent property notifications explicit.
|
||||
* Avoid hidden notification chains that are difficult to reason about.
|
||||
* Prefer reusable base implementations only when they reduce duplication without obscuring behavior.
|
||||
* Do not use reflection-based notification mechanisms unless there is a concrete benefit.
|
||||
|
||||
## Commands
|
||||
|
||||
* Prefer commands over click handlers for ViewModel-driven actions.
|
||||
* Keep command execution focused.
|
||||
* Avoid putting large workflows directly inside command implementations.
|
||||
* Keep `CanExecute` logic cheap.
|
||||
* Refresh command availability only when relevant state changes.
|
||||
* Avoid command implementations with hidden side effects.
|
||||
* Handle async commands safely.
|
||||
* Prevent accidental duplicate execution when an async action must not run concurrently.
|
||||
* Never use `async void` except for true event handlers.
|
||||
|
||||
## Async and Threading
|
||||
|
||||
* Keep async operations asynchronous throughout the call chain.
|
||||
* Avoid `.Result`, `.Wait()` and other synchronous blocking of async work.
|
||||
* Do not block the UI thread.
|
||||
* Run I/O asynchronously.
|
||||
* Move expensive CPU work off the UI thread only when necessary.
|
||||
* Marshal UI updates back to the UI thread when required.
|
||||
* Keep Dispatcher usage minimal and explicit.
|
||||
* Do not use the Dispatcher to hide incorrect threading design.
|
||||
* Support `CancellationToken` for cancellable long-running operations.
|
||||
* Cancel obsolete work when views or selections change.
|
||||
* Prevent race conditions caused by overlapping async operations.
|
||||
* Handle exceptions from background operations explicitly.
|
||||
|
||||
## UI Thread
|
||||
|
||||
* Treat the UI thread as a scarce resource.
|
||||
* Avoid expensive loops, parsing, serialization, database access or network calls on the UI thread.
|
||||
* Avoid excessive Dispatcher invocations.
|
||||
* Batch UI updates where practical.
|
||||
* Do not update UI-bound collections excessively in tight loops.
|
||||
* Avoid synchronous waits on background work.
|
||||
* Keep rendering-related callbacks lightweight.
|
||||
|
||||
## Collections
|
||||
|
||||
* Use `ObservableCollection<T>` only when collection change notifications are required.
|
||||
* Do not use `ObservableCollection<T>` as a general-purpose collection.
|
||||
* Use `List<T>` or other suitable collections for non-observable internal data.
|
||||
* Avoid replacing entire observable collections when incremental updates are sufficient.
|
||||
* Avoid thousands of individual collection notifications when a bulk update is more appropriate.
|
||||
* Keep collection mutations on the correct thread.
|
||||
* Avoid exposing mutable internal collections unnecessarily.
|
||||
* Prefer read-only views where consumers should not modify data.
|
||||
|
||||
## XAML
|
||||
|
||||
* Keep XAML readable and focused.
|
||||
* Avoid excessively large view files.
|
||||
* Split complex views into focused controls when it improves maintainability.
|
||||
* Use resources for repeated values and styles.
|
||||
* Avoid magic numbers in XAML.
|
||||
* Keep styles and templates consistent.
|
||||
* Avoid excessive inline styling.
|
||||
* Prefer reusable resources over duplicated markup.
|
||||
* Avoid deeply nested panels.
|
||||
* Keep visual trees as shallow as practical.
|
||||
* Use semantic control choices.
|
||||
* Avoid unnecessary containers.
|
||||
* Do not overuse triggers when simpler state representation is possible.
|
||||
* Keep templates understandable.
|
||||
* Avoid XAML tricks that make behavior hard to discover.
|
||||
|
||||
## Layout
|
||||
|
||||
* Prefer `Grid` for structured layouts.
|
||||
* Use `StackPanel` only where its layout behavior is actually appropriate.
|
||||
* Avoid unnecessary nested panels.
|
||||
* Avoid fixed sizes unless the design requires them.
|
||||
* Prefer responsive sizing with `Auto` and `*`.
|
||||
* Avoid layout configurations that cause excessive measure/arrange passes.
|
||||
* Be careful with large visual trees inside scrolling containers.
|
||||
* Avoid disabling virtualization accidentally.
|
||||
|
||||
## Virtualization
|
||||
|
||||
* Keep UI virtualization enabled for large collections.
|
||||
* Do not use container layouts that disable virtualization without a reason.
|
||||
* Avoid wrapping large virtualized item lists in additional scrolling containers.
|
||||
* Use virtualizing panels where appropriate.
|
||||
* Verify virtualization when displaying large data sets.
|
||||
* Avoid rendering thousands of controls simultaneously.
|
||||
* Prefer paging, incremental loading or virtualization for very large data sets.
|
||||
|
||||
## Resources and Styles
|
||||
|
||||
* Use shared resources for repeated styles, brushes, templates and dimensions.
|
||||
* Keep resource dictionaries focused.
|
||||
* Avoid giant global resource dictionaries.
|
||||
* Prefer feature-level resources when styles are not truly global.
|
||||
* Use `StaticResource` by default.
|
||||
* Use `DynamicResource` only when runtime resource replacement is required.
|
||||
* Avoid excessive dynamic resource lookups.
|
||||
* Keep theme resources separated from application logic.
|
||||
* Avoid hardcoded colors and dimensions when design tokens or resources already exist.
|
||||
|
||||
## Dependency Properties
|
||||
|
||||
* Use dependency properties only when WPF property-system behavior is required.
|
||||
* Do not use dependency properties as a replacement for normal CLR properties.
|
||||
* Keep metadata and callbacks lightweight.
|
||||
* Avoid expensive work in property-changed callbacks.
|
||||
* Avoid callbacks with hidden side effects.
|
||||
* Validate or coerce values only when the control contract requires it.
|
||||
* Do not expose mutable default values in dependency property metadata.
|
||||
|
||||
## Attached Properties and Behaviors
|
||||
|
||||
* Use attached properties and behaviors for reusable view-specific behavior.
|
||||
* Do not use them to hide business logic.
|
||||
* Keep behaviors focused and predictable.
|
||||
* Clean up event handlers when behaviors are detached.
|
||||
* Avoid global attached-property state.
|
||||
* Prefer explicit behavior over complex XAML hacks.
|
||||
|
||||
## Events
|
||||
|
||||
* Avoid unnecessary event subscriptions.
|
||||
* Unsubscribe from long-lived publishers when required.
|
||||
* Prevent memory leaks from event handlers.
|
||||
* Prefer weak events where publisher lifetime significantly exceeds subscriber lifetime.
|
||||
* Keep event handlers small.
|
||||
* Do not use events as hidden global communication channels.
|
||||
* Avoid excessive event chaining.
|
||||
|
||||
## Memory Management
|
||||
|
||||
* Watch for memory leaks caused by:
|
||||
|
||||
* Event subscriptions
|
||||
* Timers
|
||||
* Static references
|
||||
* Long-lived services
|
||||
* Cached views
|
||||
* Closures
|
||||
* Collection views
|
||||
* Binding-related references
|
||||
* Dispose resources correctly.
|
||||
* Stop timers and background work when no longer needed.
|
||||
* Avoid retaining closed windows or unloaded views.
|
||||
* Do not keep unnecessary references to visual elements.
|
||||
* Profile memory when long-running applications continuously grow.
|
||||
|
||||
## Windows and Dialogs
|
||||
|
||||
* Keep window lifecycle explicit.
|
||||
* Avoid creating duplicate windows unintentionally.
|
||||
* Do not keep hidden windows alive without a reason.
|
||||
* Separate dialog logic from business logic.
|
||||
* Prefer dialog services when ViewModels need to request user interaction.
|
||||
* Keep ownership relationships explicit.
|
||||
* Avoid application shutdown behavior that depends on accidental window lifetime.
|
||||
|
||||
## Navigation
|
||||
|
||||
* Keep navigation state explicit.
|
||||
* Avoid coupling ViewModels directly to concrete views.
|
||||
* Avoid service locator patterns for view resolution.
|
||||
* Keep navigation history intentional.
|
||||
* Dispose or release navigation targets when they are no longer required.
|
||||
* Do not retain entire navigation graphs unnecessarily.
|
||||
|
||||
## Validation
|
||||
|
||||
* Validate user input at the appropriate boundary.
|
||||
* Keep validation logic out of XAML when it becomes complex.
|
||||
* Prefer reusable validation rules or ViewModel validation for non-trivial cases.
|
||||
* Display validation errors consistently.
|
||||
* Do not rely on UI validation as a security boundary.
|
||||
* Validate again at backend or domain boundaries when required.
|
||||
* Preserve user input on recoverable errors.
|
||||
|
||||
## Performance
|
||||
|
||||
* Keep the UI thread responsive.
|
||||
* Minimize visual tree depth.
|
||||
* Keep virtualization enabled.
|
||||
* Avoid unnecessary bindings.
|
||||
* Avoid unnecessary converters.
|
||||
* Avoid unnecessary resource lookups.
|
||||
* Avoid unnecessary property change notifications.
|
||||
* Avoid frequent full collection refreshes.
|
||||
* Avoid loading large datasets eagerly.
|
||||
* Avoid loading large images at full resolution when unnecessary.
|
||||
* Freeze `Freezable` objects where practical.
|
||||
* Reuse immutable resources where appropriate.
|
||||
* Avoid unnecessary animations.
|
||||
* Avoid high-frequency timers on the UI thread.
|
||||
* Measure startup time, UI responsiveness, memory usage and rendering performance before micro-optimizing.
|
||||
|
||||
## Images and Media
|
||||
|
||||
* Load images at an appropriate resolution.
|
||||
* Avoid decoding images significantly larger than their displayed size.
|
||||
* Release streams and file handles correctly.
|
||||
* Avoid locking image files unintentionally.
|
||||
* Cache images only when there is a clear memory strategy.
|
||||
* Avoid keeping large bitmaps alive unnecessarily.
|
||||
* Prefer frozen image resources when they are immutable.
|
||||
|
||||
## Security
|
||||
|
||||
* Treat all external input as untrusted.
|
||||
* Never expose secrets, credentials or tokens in UI code.
|
||||
* Do not store secrets in configuration files committed to source control.
|
||||
* Avoid leaking sensitive information through logs, dialogs or exception messages.
|
||||
* Validate file paths and external resources.
|
||||
* Do not execute external processes or files without explicit validation.
|
||||
* Avoid insecure deserialization.
|
||||
* Do not weaken TLS, authentication or certificate validation.
|
||||
* Prefer secure defaults.
|
||||
* Never disable security controls for convenience.
|
||||
|
||||
## File and Process Access
|
||||
|
||||
* Validate file paths before use.
|
||||
* Avoid assuming files or directories exist.
|
||||
* Handle permissions and locked files gracefully.
|
||||
* Avoid arbitrary shell execution.
|
||||
* Quote and validate process arguments safely.
|
||||
* Do not concatenate untrusted input into shell commands.
|
||||
* Avoid elevated privileges unless explicitly required.
|
||||
* Clean up temporary files when appropriate.
|
||||
|
||||
## Error Handling
|
||||
|
||||
* Handle expected errors explicitly.
|
||||
* Do not swallow exceptions.
|
||||
* Preserve useful exception context.
|
||||
* Avoid showing raw technical exceptions directly to end users.
|
||||
* Log enough information for diagnosis without exposing sensitive data.
|
||||
* Keep user-facing error messages clear and actionable.
|
||||
* Avoid using exceptions for normal control flow.
|
||||
* Ensure background exceptions are observed.
|
||||
|
||||
## Logging
|
||||
|
||||
* Use structured logging.
|
||||
* Avoid excessive logging on the UI thread.
|
||||
* Do not log every property change or binding update.
|
||||
* Never log secrets, tokens, credentials or sensitive user data.
|
||||
* Include relevant context for operational failures.
|
||||
* Avoid logging the same exception repeatedly at multiple layers.
|
||||
|
||||
## Architecture
|
||||
|
||||
* Keep presentation, application, domain and infrastructure concerns separated.
|
||||
* Avoid direct database access from views or ViewModels.
|
||||
* Avoid direct HTTP access from controls.
|
||||
* Keep external integrations behind focused services.
|
||||
* Avoid circular dependencies.
|
||||
* Keep feature boundaries clear.
|
||||
* Do not create shared utility classes for unrelated functionality.
|
||||
* Keep shared code genuinely reusable.
|
||||
* Minimize global state.
|
||||
* Avoid static service access.
|
||||
|
||||
## Dependency Injection
|
||||
|
||||
* Use dependency injection where lifecycle management, substitution or testability benefits from it.
|
||||
* Avoid service locator patterns.
|
||||
* Keep constructor dependencies minimal.
|
||||
* Do not inject dependencies that are not used.
|
||||
* Choose service lifetimes intentionally.
|
||||
* Do not make stateful services global without a concrete reason.
|
||||
* Avoid introducing interfaces solely for dependency injection when no abstraction is needed.
|
||||
|
||||
## Testing
|
||||
|
||||
* Keep ViewModels testable without a UI thread where practical.
|
||||
* Test behavior rather than implementation details.
|
||||
* Test domain and application logic independently from WPF.
|
||||
* Avoid brittle tests coupled to XAML structure.
|
||||
* Keep UI automation tests focused on critical flows.
|
||||
* Mock external boundaries rather than internal details.
|
||||
* Keep tests deterministic.
|
||||
* Avoid real network, database or filesystem dependencies in unit tests unless explicitly intended.
|
||||
|
||||
## Code Quality
|
||||
|
||||
* Use nullable reference types.
|
||||
* Prefer modern, readable C# syntax.
|
||||
* Avoid unnecessary interfaces and abstractions.
|
||||
* Prefer concrete types where no abstraction is required.
|
||||
* Use descriptive names.
|
||||
* Remove dead code.
|
||||
* Remove commented-out code.
|
||||
* Do not add comments unless the user explicitly requests them.
|
||||
* Treat compiler, analyzer and binding warnings seriously.
|
||||
* Do not suppress warnings without a concrete reason.
|
||||
* Prefer correctness, responsiveness, security and maintainability over cleverness.
|
||||
|
||||
## Performance Priority
|
||||
|
||||
Prioritize WPF performance work in this order:
|
||||
|
||||
* UI architecture
|
||||
* UI thread blocking
|
||||
* Data loading and I/O
|
||||
* Virtualization
|
||||
* Visual tree complexity
|
||||
* Binding and notification frequency
|
||||
* Rendering and images
|
||||
* Memory retention and leaks
|
||||
* Allocations
|
||||
* CPU micro-optimizations
|
||||
|
||||
Never optimize based purely on assumptions.
|
||||
|
||||
## Safety Rule
|
||||
|
||||
* The UI must remain responsive.
|
||||
* Do not block the UI thread with I/O or expensive CPU work.
|
||||
* Do not bypass validation or security controls for convenience.
|
||||
* Do not introduce hidden cross-thread access.
|
||||
* Prefer predictable, explicit and testable UI behavior.
|
||||
@@ -0,0 +1,17 @@
|
||||
---
|
||||
name: debugging
|
||||
description: Investigate and resolve software defects using evidence.
|
||||
---
|
||||
|
||||
# Debugging
|
||||
|
||||
Use when behavior is incorrect, failing, or unexpectedly slow.
|
||||
|
||||
1. Reproduce or isolate the problem.
|
||||
2. Gather evidence and identify the likely cause.
|
||||
3. Apply the smallest complete fix.
|
||||
4. Run relevant verification.
|
||||
|
||||
Return the cause, change, and verification result.
|
||||
|
||||
Do not guess when evidence can be collected.
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
name: answer-pull-request
|
||||
description: Prepare a clear response to pull request feedback.
|
||||
---
|
||||
|
||||
# Answer Pull Request
|
||||
|
||||
Understand each comment, make authorized changes, and respond with evidence.
|
||||
|
||||
Separate completed actions, explanations, and unresolved questions.
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
name: review-pull-request
|
||||
description: Review a pull request for correctness, risk, and readiness.
|
||||
---
|
||||
|
||||
# Review Pull Request
|
||||
|
||||
Inspect the change and its context independently.
|
||||
|
||||
Report actionable findings first, followed by verification status and open risks.
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
name: integration-test-write
|
||||
description: Add focused integration tests for connected system behavior.
|
||||
---
|
||||
|
||||
# Integration Test Write
|
||||
|
||||
Identify the integration boundary, required setup, and meaningful success and failure cases.
|
||||
|
||||
Keep the test deterministic and limited to the behavior under change.
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
name: sql-write
|
||||
description: Implement a focused SQL change safely.
|
||||
---
|
||||
|
||||
# SQL Write
|
||||
|
||||
Understand the schema and affected data before writing SQL.
|
||||
|
||||
Use the smallest complete change, preserve data safety, and run relevant verification.
|
||||
|
||||
Do not execute destructive operations without explicit authorization.
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
name: unit-test-write
|
||||
description: Add focused unit tests for isolated behavior.
|
||||
---
|
||||
|
||||
# Unit Test Write
|
||||
|
||||
Identify the behavior and important boundary cases, then add focused deterministic tests.
|
||||
|
||||
Prefer observable behavior over implementation details. Report the checks that were run.
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
name: change-impact-analysis
|
||||
description: Determine what a proposed change may affect.
|
||||
---
|
||||
|
||||
# Change Impact Analysis
|
||||
|
||||
Use when the blast radius or compatibility impact is uncertain.
|
||||
|
||||
Inspect callers, dependencies, configuration, tests, and affected workflows.
|
||||
|
||||
Return affected areas, risks, and recommended verification. Separate facts from assumptions.
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
name: implementation-planner
|
||||
description: Create a concise plan for implementing an understood change.
|
||||
---
|
||||
|
||||
# Implementation Planner
|
||||
|
||||
Use before implementation when a change has multiple meaningful steps.
|
||||
|
||||
Identify the goal, affected areas, sequence, risks, and verification.
|
||||
|
||||
Return a short actionable plan. Do not implement the change.
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
name: work-item-definition
|
||||
description: Turn an unclear request into a bounded technical work item.
|
||||
---
|
||||
|
||||
# Work Item Definition
|
||||
|
||||
Use when requirements, scope, or acceptance criteria are incomplete.
|
||||
|
||||
Clarify the objective, boundaries, assumptions, acceptance criteria, and open questions.
|
||||
|
||||
Do not invent business requirements.
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
name: repository-research
|
||||
description: Investigate an existing repository to find relevant code and established patterns.
|
||||
---
|
||||
|
||||
# Repository Research
|
||||
|
||||
Use before changing an unfamiliar repository area.
|
||||
|
||||
Inspect relevant files, callers, tests, configuration, and established patterns.
|
||||
|
||||
Return evidence, affected areas, unknowns, and useful implementation context. Avoid modifying implementation code.
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
name: technical-research
|
||||
description: Investigate technical options and relevant evidence before implementation.
|
||||
---
|
||||
|
||||
# Technical Research
|
||||
|
||||
Use when an implementation depends on unfamiliar technology, APIs, tools, or trade-offs.
|
||||
|
||||
Gather relevant evidence, compare viable options, and identify unknowns.
|
||||
|
||||
Return concise findings with sources, assumptions, and a recommendation when appropriate. Do not implement the change.
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
name: api-review
|
||||
description: Review API changes for compatibility and contract clarity.
|
||||
---
|
||||
|
||||
# API Review
|
||||
|
||||
Inspect request and response contracts, validation, errors, authorization, compatibility, and documentation.
|
||||
|
||||
Return concrete findings and affected consumers. Keep detailed API standards for future customization.
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
name: business-review
|
||||
description: Review a change against stated business intent and workflows.
|
||||
---
|
||||
|
||||
# Business Review
|
||||
|
||||
Check actors, workflows, domain concepts, invariants, edge cases, and acceptance criteria.
|
||||
|
||||
Separate stated requirements, evidence, and assumptions. Do not invent business requirements.
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
name: code-review
|
||||
description: Review code for correctness, maintainability, and regressions.
|
||||
---
|
||||
|
||||
# Code Review
|
||||
|
||||
Inspect the change independently and report concrete findings with severity and evidence.
|
||||
|
||||
Check behavior, regressions, maintainability, unnecessary complexity, and verification.
|
||||
|
||||
Do not modify code unless explicitly asked.
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
name: efcore-review
|
||||
description: Review Entity Framework Core changes for correctness and data access risks.
|
||||
---
|
||||
|
||||
# EF Core Review
|
||||
|
||||
Inspect queries, relationships, tracking, migrations, transactions, and performance-sensitive access.
|
||||
|
||||
Return concrete findings and relevant verification. Keep detailed EF Core standards for future customization.
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
name: performance-review
|
||||
description: Review changes for meaningful performance risks.
|
||||
---
|
||||
|
||||
# Performance Review
|
||||
|
||||
Identify measurable or plausible bottlenecks in the changed paths.
|
||||
|
||||
Return evidence, expected impact, and proportionate recommendations. Avoid speculative optimization.
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
name: security-review
|
||||
description: Review changes for concrete security weaknesses.
|
||||
---
|
||||
|
||||
# Security Review
|
||||
|
||||
Inspect trust boundaries, input handling, authorization, secrets, permissions, and sensitive data.
|
||||
|
||||
Return evidence, impact, and actionable findings. Do not invent vulnerabilities without evidence.
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
name: ui-ux-review
|
||||
description: Review user interface changes for usability and consistency.
|
||||
---
|
||||
|
||||
# UI UX Review
|
||||
|
||||
Inspect states, feedback, accessibility basics, consistency, and error handling.
|
||||
|
||||
Return concrete findings with affected user flows. Keep detailed design standards for future customization.
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
name: wpf-review
|
||||
description: Review WPF changes for correctness and maintainability.
|
||||
---
|
||||
|
||||
# WPF Review
|
||||
|
||||
Inspect the changed WPF views, bindings, resources, commands, and lifecycle behavior.
|
||||
|
||||
Return concrete findings and relevant verification. Keep detailed WPF standards for future customization.
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
name: facts-verification
|
||||
description: Verify factual claims against available evidence.
|
||||
---
|
||||
|
||||
# Facts Verification
|
||||
|
||||
Check important claims against source code, documentation, commands, or other appropriate evidence.
|
||||
|
||||
Return the claim, evidence, and confidence. Mark unknowns explicitly.
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
name: regression-verification
|
||||
description: Check that existing behavior was not unintentionally broken.
|
||||
---
|
||||
|
||||
# Regression Verification
|
||||
|
||||
Identify the affected existing behavior and run proportionate regression checks.
|
||||
|
||||
Report results and any unverified areas. Do not claim checks that were not run.
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
name: work-item-verification
|
||||
description: Verify that a work item meets its stated acceptance criteria.
|
||||
---
|
||||
|
||||
# Work Item Verification
|
||||
|
||||
Compare the completed change with its requirements and acceptance criteria.
|
||||
|
||||
Return passed criteria, failed criteria, checks run, and remaining limitations.
|
||||
@@ -0,0 +1,11 @@
|
||||
$data = ($input | Out-String) | ConvertFrom-Json
|
||||
$model = if ($data.model.display_name) { $data.model.display_name } else { '-' }
|
||||
$effort = if ($data.effort.level) { $data.effort.level } else { '-' }
|
||||
$directory = if ($data.workspace.current_dir) { $data.workspace.current_dir } else { $data.cwd }
|
||||
$repo = if ($data.workspace.repo.name) { $data.workspace.repo.name } elseif ($directory) { Split-Path $directory -Leaf } else { '-' }
|
||||
$branch = if ($directory -and (Get-Command git -ErrorAction SilentlyContinue)) { (& git -C $directory branch --show-current 2>$null | Select-Object -First 1) } else { $null }
|
||||
if (-not $branch) { $branch = '-' }
|
||||
$maxContext = if ($data.context_window.context_window_size) { [long]$data.context_window.context_window_size } else { 0 }
|
||||
$usedContext = if ($null -ne $data.context_window.used_percentage) { "$([math]::Round([double]$data.context_window.used_percentage, [MidpointRounding]::AwayFromZero))%" } else { '-' }
|
||||
$usedTokens = [long]$data.context_window.total_input_tokens + [long]$data.context_window.total_output_tokens
|
||||
Write-Output "Model: $model | Effort: $effort | Repo: $repo | Branch: $branch | Max Context: $maxContext | Used Context: $usedContext | Used Tokens: $usedTokens"
|
||||
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
command -v jq >/dev/null 2>&1 || exit 0
|
||||
input=
|
||||
while IFS= read -r line || [ -n "$line" ]; do input+="$line"; done
|
||||
IFS=$'\t' read -r model effort repo directory max_context used_context used_tokens < <(
|
||||
printf '%s' "$input" | jq -r '[
|
||||
(.model.display_name // "-"),
|
||||
(.effort.level // "-"),
|
||||
(.workspace.repo.name // "-"),
|
||||
(.workspace.current_dir // .cwd // "."),
|
||||
(.context_window.context_window_size // 0),
|
||||
(if .context_window.used_percentage == null then "-" else ((.context_window.used_percentage | round | tostring) + "%") end),
|
||||
((.context_window.total_input_tokens // 0) + (.context_window.total_output_tokens // 0))
|
||||
] | @tsv'
|
||||
)
|
||||
[ "$repo" != - ] || repo=$(basename -- "$directory")
|
||||
[ -n "$repo" ] || repo=-
|
||||
branch=$(git -C "$directory" branch --show-current 2>/dev/null || true)
|
||||
[ -n "$branch" ] || branch=-
|
||||
printf 'Model: %s | Effort: %s | Repo: %s | Branch: %s | Max Context: %s | Used Context: %s | Used Tokens: %s\n' "$model" "$effort" "$repo" "$branch" "$max_context" "$used_context" "$used_tokens"
|
||||
Reference in new issue
Block a user