Skip to content

Commit 69e7cd0

Browse files
Merge branch 'main' into docs/gha-standard-diagnostics
2 parents beb545e + cc8e543 commit 69e7cd0

6 files changed

Lines changed: 64 additions & 4 deletions

File tree

src/docs/Coding-Standards/Markdown.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,12 @@ These rules are disabled or widened so they do not flag valid documentation —
5454
- **Surround headings, lists, and fenced blocks with a blank line** for readability, even though the linter no longer enforces it.
5555
- **Prefer relative links** within a repository; use the canonical published URL for cross-repository references.
5656
- **Tag every code fence with a language** (` ```bash `, ` ```yaml `) so it is highlighted and converts cleanly when published.
57+
58+
## PowerShell code samples
59+
60+
Documentation is full of PowerShell, so present it the way the [PowerShell standard](PowerShell/index.md) writes it:
61+
62+
- **Label the fence `powershell`**, and put command output in a separate block labelled `Output`, so it is neither syntax-highlighted as a command nor mistaken for input.
63+
- **Use full cmdlet and parameter names**, and avoid positional parameters, so a reader can copy the sample and run it.
64+
- **Avoid backtick line-continuation.** Break a long call with splatting, or at PowerShell's natural points — after a pipe, an opening parenthesis, or a brace.
65+
- **Leave out the prompt string** (`PS>`) unless the sample is specifically about interactive, prompt-changing behaviour.

src/docs/Coding-Standards/PowerShell/Functions.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,21 @@ function Get-UserData {
6666
## Errors and output
6767

6868
- **`throw` for terminating errors**; `Write-Error` only where the caller is expected to handle a non-terminating one.
69-
- **Emit one object type**, matching `[OutputType()]`; never `Write-Host` data another command might consume.
69+
- **Call cmdlets you mean to trap with `-ErrorAction Stop`** so they raise terminating, catchable errors. Native commands report failure through `$LASTEXITCODE`, not the error stream, so check it and `throw` yourself — or set `$PSNativeCommandUseErrorActionPreference = $true` on PowerShell 7.4+ so their non-zero exits honour `$ErrorActionPreference` too.
70+
- **Put the whole transaction in the `try` block** rather than setting success flags to gate later code, and do not lean on `$?` — it reports only whether the last command considered itself successful, with no detail.
71+
- **In a `catch`, copy `$_` into your own variable first**, before later commands overwrite it. The baseline rules — fail fast, never swallow — live in [Error Handling](../Error-Handling.md).
72+
73+
## Output streams
74+
75+
Send each kind of message to the stream built for it, so a caller can capture, redirect, or silence it:
76+
77+
- **Results** are objects on the output stream — emit them implicitly by naming the object on its own line; do **not** use `return $obj` to emit, and in a pipeline function emit from `process`, not `end`.
78+
- **Emit one object type**, matching `[OutputType()]`.
79+
- **`Write-Verbose`** for status a caller may want (`-Verbose`), **`Write-Debug`** for maintainer breadcrumbs (`-Debug`), and **`Write-Progress`** for progress that need not persist.
80+
- **`Write-Warning`** and **`Write-Error`** for warnings and non-terminating errors.
81+
- **`Write-Host`** only for `Show-` or `Format-` verbs or an interactive prompt — never for data another command might consume.
82+
83+
`[CmdletBinding()]` is what turns on the `-Verbose` and `-Debug` switches, so those streams reach the caller.
7084

7185
## Comment-based help (required)
7286

src/docs/Coding-Standards/PowerShell/Scripts.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,8 @@ $ErrorActionPreference = 'Stop'
4848
- **Name scripts `Verb-Noun.ps1`** to match the function convention.
4949
- **No side effects on load.** A script runs top to bottom when invoked; it should not do work merely by being dot-sourced.
5050
- **Return objects**, so the script composes in a pipeline like any other command.
51+
52+
## Paths
53+
54+
- **Do not depend on the current directory.** Avoid relative paths and `~` — the meaning of `~` depends on the current PowerShell provider — and build paths from `$PSScriptRoot` with `Join-Path`.
55+
- **Pass full paths to .NET and native calls.** .NET methods and external executables resolve relative paths against `[System.Environment]::CurrentDirectory`, which PowerShell does not keep reliably in step with `$PWD` — it can lag `Set-Location`, and diverges in non-FileSystem providers (`Registry`, `Cert:`). Resolve to a full path first.

src/docs/Coding-Standards/PowerShell/index.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,23 @@ This standard builds on the [language-agnostic baseline](../index.md); where the
1919

2020
<!-- INDEX:END -->
2121

22+
## Tools and controllers
23+
24+
PowerShell falls into two kinds, and the difference decides how a command shapes its output:
25+
26+
- A **tool** is a reusable unit — an advanced function, usually exported from a module. It takes input only through parameters and emits **raw, least-manipulated objects**, so it stays usable in situations its author never imagined; a tool that measures a size returns bytes, not a rounded string.
27+
- A **controller** is a script that automates one process by calling tools. It may reshape, round, or format data for how it will be read, and it is not meant to be reused.
28+
29+
Keep the shaping at the edge: tools stay general and emit raw objects, and a controller — or a format view (`.format.ps1xml`) — turns those into presentation. This is the [thin script](Scripts.md) rule seen from the other side, and it is why tools [emit objects, not text](#shared-conventions).
30+
2231
## Shared conventions
2332

2433
These hold for all PowerShell, whatever the construct:
2534

2635
- **`Verb-Noun` naming** with an approved verb (`Get-Verb`) and a singular noun: `Get-RepositorySecret`, not `Fetch-Secrets`.
2736
- **`PascalCase`** for functions, parameters, public variables, and class members; `camelCase` for local variables.
2837
- **Full cmdlet names, never aliases** (`Where-Object`, not `?`; `ForEach-Object`, not `%`).
38+
- **Full parameter names, and standard ones.** Pass parameters by name and avoid positional arguments in shared code — `Get-Process -Name pwsh`, not `Get-Process pwsh` — so a call survives parameter-set changes and reads clearly. Name your own parameters after PowerShell's built-ins (`Path`, `Name`, `ComputerName`), not `$Param_Computer`.
2939
- **Set `$ErrorActionPreference = 'Stop'`** at the top of every script and module so errors are terminating, not silently swallowed.
3040
- **Emit objects, not formatted text.** Return rich objects and let the caller format; reserve `Write-Host` for genuine console UX, and use `Write-Verbose` / `Write-Information` for progress narration.
3141

@@ -49,7 +59,7 @@ Beyond the basics, these language-specific habits keep PowerShell correct and fa
4959
- **Put `$null` on the left of a comparison**`$null -eq $x`, never `$x -eq $null`. Against a collection the right-hand form *filters* rather than tests. Use `-contains` / `-in` for membership, never `-eq`.
5060
- **Suppress unwanted output with `$null = ...`** (or `[void]` for method calls), not `| Out-Null` — the pipeline form is markedly slower on hot paths.
5161
- **Build collections with a typed list, not `+=` in a loop.** `$a += $x` reallocates the whole array every iteration; use `[System.Collections.Generic.List[T]]` with `.Add()`, and prefer a cmdlet's `-Filter` over piping to `Where-Object` on large sets.
52-
- **Keep secrets out of source, and never `Invoke-Expression` untrusted input.** Take secrets as `[securestring]` or through `Get-Credential`, and guard state-changing commands with `ShouldProcess` (see [Functions](Functions.md)); the wider rules live in the [Security](../Security.md) baseline.
62+
- **Keep secrets out of source, and never `Invoke-Expression` untrusted input.** Accept credentials as a `[PSCredential]` parameter with the `[Credential()]` attribute rather than calling `Get-Credential` inside a reusable function, so a caller can pass one they already hold, and take other sensitive values as `[securestring]`. Guard state-changing commands with `ShouldProcess` (see [Functions](Functions.md)); the wider rules live in the [Security](../Security.md) baseline.
5363

5464
## Toolchain
5565

src/docs/Ways-of-Working/Principles/Software-Design.md

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
title: Software design
3-
description: SOLID, extensibility, DRY with judgment, and making change easy before making the change.
3+
description: SOLID, extensibility, smart defaults with local overrides, DRY with judgment, and making change easy before making the change.
44
---
55

66
# Software design
@@ -19,6 +19,28 @@ Extend by adding, not by modifying what already works — the Open/Closed princi
1919

2020
The system stays pluggable: the docs do not change when a new agent runtime is added — only a new integration layer is written. See the [Agentic Development](../Agentic-Development.md) specification for how this plays out in practice.
2121

22+
## Smart defaults, local overrides
23+
24+
The default is the smart, secure choice — what you would pick most of the time, and the safe option when unsure. A system with no configuration is already correct, safe, and useful out of the box. Configuration exists to *deviate* from a good default, never to reach a usable one.
25+
26+
Set the default at the broadest scope, and let each narrower scope override it. The setting closest to the thing it controls wins:
27+
28+
```text
29+
org / ecosystem the widest default — set once, inherited everywhere
30+
└── repository may narrow the default for one codebase
31+
└── directory may narrow it further for one area
32+
└── item the last word — closest to what it configures
33+
```
34+
35+
This shape is chosen for manageability over the life of a system, and it earns two properties at once:
36+
37+
- **Manageable across the wide.** Change the default in one place and everything that has not opted out follows. You set the norm once instead of finding and editing many copies of it.
38+
- **Flexible in the narrow.** Deviating is a small, local edit beside the item that needs it — not a fight with the system, and not a change that ripples outward. The exception lives with the thing it applies to.
39+
40+
Make the wide default easy to set and the local override easy to make. When the two disagree, the more specific one wins — predictably, by its position in the hierarchy, never by special-casing.
41+
42+
This is [Easy and Safe](../../index.md) expressed as design: doing the right thing takes no effort because it is the default, and deviating is deliberate and contained because it is a local override. [Least-privilege](Purpose-and-Direction.md#least-privilege) and [secure by default](../../Coding-Standards/Security.md#secure-by-default) are this principle applied to permissions and security; the way [the vision cascades](../../Vision/index.md#how-the-vision-cascades) is its shape applied to knowledge.
43+
2244
## DRY — with judgment
2345

2446
Don't Repeat Yourself, but **don't extract too early**. Wait until the same non-trivial logic appears in three or more places, or until the duplication is clearly load-bearing. Premature abstraction is more expensive than duplication.

src/docs/Ways-of-Working/Principles/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Principles are grouped by theme; each theme is its own page so an agent can load
1515
| --- | --- |
1616
| [Purpose and direction](Purpose-and-Direction.md) | Why we build, who we build for, and the least-privilege stance under every decision. |
1717
| [AI-first development](AI-First-Development.md) | Agents as first-class participants, determinism before intelligence, and how humans and agents share the work. |
18-
| [Software design](Software-Design.md) | SOLID, extensibility, DRY with judgment, and making change easy before making the change. |
18+
| [Software design](Software-Design.md) | SOLID, extensibility, smart defaults with local overrides, DRY with judgment, and making change easy before making the change. |
1919
| [Engineering practices](Engineering-Practices.md) | Write it down, everything as code, evergreen docs, test-driven development, and shift-left quality. |
2020
| [Planning and delivery](Planning-and-Delivery.md) | Roadmapping, lean delivery, and the loops that keep iteration fast. |
2121
| [References](References.md) | The literature behind these principles. |

0 commit comments

Comments
 (0)