Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions docs-out/.work/cf/COORD.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"cfs": [],
"deviations": [
{
"id": "DEV-DESIGN-110",
"baseline_behavior": "PowerShell compiles to expression trees and uses Reflection.Emit for classes.",
"proposed_behavior": "MicroteamShell starts with a tree-walking evaluator and does not adopt Reflection.Emit or Expression.Compile as the core engine.",
"benefit": "AOT-friendly, debuggable, small.",
"compatibility_cost": "Lower peak throughput; classes (if added) are interpreter objects.",
"affected_cfs": [
"CF-CMP-001"
],
"status": "PROPOSED"
}
]
}
5 changes: 3 additions & 2 deletions docs-out/.work/cf/T27.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,14 @@
{
"id": "CF-CMP-003",
"subject": "optimized-versus-unoptimized preconditions",
"statement": "**Optimized versus unoptimized.** A script block clause is run from the optimized code (variables in fixed tuple slots) only if the engine is not debugging (`ExecutionContext._debuggingMode <= 0`) **and** the invocation creates a new local scope (`createLocalScope`, i.e. not dot-sourced); the same two conditions are used for script cmdlets. If the optimized compile shows that any slot-allocated variable name could be an `AllScope` variable (`VariableAnalysis.AnyVariablesCouldBeAllScope`), the unoptimized variant is used instead, and both variants are compiled. In the unoptimized variant only the automatic variables (plus the preference variables for script cmdlets) get tuple slots and every other variable is looked up by name. Independently of this choice, variable analysis allocates no slots for a block that uses `New-Variable`, `Remove-Variable`, `Set-Variable`, `Set-PSBreakpoint` (or their aliases), dot-sourcing or `$private:` variables.",
"statement": "**Optimized versus unoptimized.** A script block clause is run from the optimized code (variables in fixed tuple slots) only if the engine is not debugging (`ExecutionContext._debuggingMode <= 0`) **and** the invocation creates a new local scope (`createLocalScope`, i.e. not dot-sourced); the same two conditions are used by the command processors that run script blocks (`DlrScriptCommandProcessor` constructor) and script cmdlets. If the optimized compile shows that any slot-allocated variable name could be an `AllScope` variable (`VariableAnalysis.AnyVariablesCouldBeAllScope`), the unoptimized variant is used instead, and both variants are compiled. In the unoptimized variant only the automatic variables (plus the preference variables for script cmdlets) get tuple slots and every other variable is looked up by name. Independently of this choice, variable analysis allocates no slots for a block that uses `New-Variable`, `Remove-Variable`, `Set-Variable`, `Set-PSBreakpoint` (or their aliases), dot-sourcing or `$private:` variables.",
"label": "FACT-SRC",
"evidence": [
"src/System.Management.Automation/engine/runtime/CompiledScriptBlock.cs::CompiledScriptBlockData.Compile@L57-L83",
"src/System.Management.Automation/engine/runtime/CompiledScriptBlock.cs::ScriptBlock@L542-L2177",
"src/System.Management.Automation/engine/runtime/CompiledScriptBlock.cs::PSScriptCmdlet@L2179-L2552",
"src/System.Management.Automation/engine/parser/VariableAnalysis.cs::VariableAnalysis@L325-L1847"
"src/System.Management.Automation/engine/parser/VariableAnalysis.cs::VariableAnalysis@L325-L1847",
"src/System.Management.Automation/engine/ScriptCommandProcessor.cs::DlrScriptCommandProcessor.Init@L274-L296"
],
"owner": "02-language/TIERING-POLICY.md",
"status": "open"
Expand Down
43 changes: 43 additions & 0 deletions docs-out/.work/cf/T31.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"cfs": [
{
"id": "CF-LCY-001",
"subject": "command and script lifecycle (begin/process/end/clean, cmdlet lifecycle)",
"statement": "**Command lifecycle (CF-LCY-001).** For a pipeline of commands C1\u2026Cn the engine (1) builds all command processors and wires pipes; (2) *prepares* every command in order (parameter binding from the command line, with default parameter values applied) and sets up common-parameter variables; (3) runs the *begin* phase of every command in order C1\u2026Cn (`BeginProcessing`, or the `begin` block); (4) runs the *process* phase *depth-first and synchronously*: C1 reads its input (or runs once with no input if none is expected), and each object it writes into its output pipe causes C2 to run its process phase over everything queued (the default buffer threshold is zero), recursively; every input object is bound before each call (pipeline parameter binding, then mandatory-parameter check); an object that cannot be bound or misses a mandatory parameter produces a non-terminating error and is skipped; (5) when C1's input is exhausted the *end* phase runs for C1\u2026Cn in order \u2014 each command first drains any input still queued through its process phase, then runs `EndProcessing` (or the `end` block); (6) the *clean* phase (`clean` blocks, only for commands that have one) runs for every command in `finally`, with stopping suspended, and its errors are written to the command's error output; (7) all command processors are disposed. The first terminating error is recorded; later failures are logged as health events and do not replace it. A stop request cancels the pipeline token and calls `StopProcessing` on every command.",
"label": "FACT-SRC",
"evidence": [
"src/System.Management.Automation/engine/pipeline.cs::PipelineProcessor.Start@L1029-L1147",
"src/System.Management.Automation/engine/pipeline.cs::PipelineProcessor.DoCompleteCore@L614-L709",
"src/System.Management.Automation/engine/Pipe.cs::Pipe.AddToPipe@L435-L466",
"src/System.Management.Automation/engine/CommandProcessor.cs::CommandProcessor.Read@L452-L581",
"src/System.Management.Automation/engine/CommandProcessorBase.cs::CommandProcessorBase.Complete@L591-L609"
],
"owner": "03-runtime/runspace-and-pipeline.md",
"status": "closed"
}
],
"deviations": [
{
"id": "DEV-PIPE-110",
"baseline_behavior": "Host-facing object streams are effectively unbounded (capacity Int32.MaxValue) and a pipeline has no time or memory budget.",
"proposed_behavior": "Bounded, cancellable host streams by default plus an optional per-pipeline time/memory budget.",
"benefit": "Predictable resource use in enterprise hosts.",
"compatibility_cost": "Behavior differs for producers that exceed the bound; hosts must handle blocking or rejection.",
"affected_cfs": [
"CF-LCY-001"
],
"status": "PROPOSED"
},
{
"id": "DEV-PIPE-111",
"baseline_behavior": "An internal empty \"pulse\" pipeline is created to run pending engine events when the runspace is idle.",
"proposed_behavior": "Schedule event processing on the runspace loop without creating a pipeline.",
"benefit": "Removes a special pipeline and its state-machine corner cases.",
"compatibility_cost": "Code that observed the pulse pipeline (id 0, history) would not see it.",
"affected_cfs": [
"CF-LCY-001"
],
"status": "PROPOSED"
}
]
}
42 changes: 42 additions & 0 deletions docs-out/.work/cf/T32.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"cfs": [
{
"id": "CF-DSC-001",
"subject": "command resolution order",
"statement": "**Command resolution order (CF-DSC-001).** For one name the searcher tries, in this order and returning the first match that is allowed: (1) **alias** (a match whose visibility does not allow the caller's origin is skipped and the search continues with functions); (2) **function / filter / configuration**; (3) **cmdlet** (a module-qualified name `Module\\Cmdlet` matches only cmdlets of that module; with several cmdlets of the same name in different modules, the first in table order is returned unless all scopes are searched); (4) if application or external-script types are allowed: a name that is a *qualified provider path* is resolved as a path; then an absolute path to an existing file; then the file system search of each `PATH` directory in order (for a name with a directory part: only that directory); then a PowerShell-relative path (name starting with `.`, `~` or `\\`). Within one directory the candidate file names are, in order: the name itself first if it already has an extension; `name.ps1` when external scripts are allowed (also `.psm1` and `.psd1` in non-discovery searches); on Windows every `PATHEXT` extension when applications are allowed; then the bare name if not yet added. A `.ps1` file becomes an external script; any other existing file becomes an application. If the normal search fails and the name contains neither `-` nor `\\`, the lookup is repeated once with the name prefixed with `Get-`. If still unresolved, module-qualified names trigger module auto-loading, and (with `$PSModuleAutoLoadingPreference` = `All`, the default) other names trigger module auto-discovery against the module analysis cache; then the *command-not-found* handler runs; then a `CommandNotFoundException` is raised. In a session whose origin is `Runspace`, application and external-script types are removed from the search when the session state has no allowed applications or scripts, and a name with a directory part must match an allow-list entry (prefix match, or the list is exactly `*`).",
"label": "FACT-SRC",
"evidence": [
"src/System.Management.Automation/engine/CommandSearcher.cs::CommandSearcher.MoveNext@L78-L239",
"src/System.Management.Automation/engine/CommandDiscovery.cs::CommandDiscovery.LookupCommandInfo@L656-L793",
"src/System.Management.Automation/engine/CommandDiscovery.cs::CommandDiscovery.TryNormalSearch@L886-L949",
"src/System.Management.Automation/engine/CommandSearcher.cs::CommandSearcher.ConstructSearchPatternsFromName@L1322-L1363"
],
"owner": "03-runtime/command-discovery-and-invocation.md",
"status": "open"
}
],
"deviations": [
{
"id": "DEV-DISC-120",
"baseline_behavior": "Unknown command names trigger module auto-discovery by analyzing every module file on PSModulePath.",
"proposed_behavior": "Resolve through an explicit signed command index refreshed on module install/update; keep module-qualified auto-load.",
"benefit": "Faster misses, no file scans on typos, auditable resolution.",
"compatibility_cost": "Modules not indexed are not auto-loaded until indexed.",
"affected_cfs": [
"CF-DSC-001"
],
"status": "PROPOSED"
},
{
"id": "DEV-DISC-121",
"baseline_behavior": "Native argument passing has three styles (Legacy, Standard, Windows) with a name-based list of legacy programs.",
"proposed_behavior": "List-based passing only, with a per-command opt-in for raw command lines.",
"benefit": "Removes the quoting ambiguity and the legacy program list.",
"compatibility_cost": "Scripts relying on Legacy re-quoting need the opt-in.",
"affected_cfs": [
"CF-DSC-001"
],
"status": "PROPOSED"
}
]
}
43 changes: 43 additions & 0 deletions docs-out/.work/cf/T33.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"cfs": [
{
"id": "CF-BND-001",
"subject": "parameter-binding order and parameter-set resolution",
"statement": "**Parameter binding order and parameter-set resolution (CF-BND-001).** Command-line binding runs these steps in order: (1) arguments that came from hashtable splatting are moved after all other arguments; (2) a parameter name with no value is joined with the next argument as its value (a switch parameter takes `$true` instead; a name followed by another recognizable parameter name, or a name at the end, is a `MissingArgument` error); (3) **named binding**: every argument with a name is matched (exact name or alias first, then unambiguous prefix); a parameter already bound is an error (`ParameterAlreadyBound`) except that a splatted entry whose name was already bound explicitly is skipped; the `--%` verbatim marker is consumed here; (4) **positional binding**: unbound parameters that have a position in the still-valid sets are grouped by position number in ascending order; arguments without a name are taken in order; each is offered to the parameters of that position in four attempts \u2014 default set without type coercion, all valid sets without coercion, default set with coercion, all valid sets with coercion \u2014 and an argument no parameter accepts stays unbound; (5) values from `$PSDefaultParameterValues` are bound to still-unbound parameters, after positional binding and again after dynamic parameters; (6) `ValidateParameterSets`; (7) dynamic parameters are fetched once from the command (`GetDynamicParameters`), merged into the parameter table and set bitmasks, and named and positional binding are repeated for the leftover arguments; (8) leftover arguments are bound to the single `ValueFromRemainingArguments` parameter (two such parameters in the current sets is an error); (9) any argument still unbound is an error (`NamedParameterNotFound` for a named one, `PositionalParameterNotFound` otherwise); (10) the final parameter-set check and the mandatory-parameter step (\u00a77); (11) script parameters that are still unbound get their declared default values; (12) the set mask is saved for pipeline binding. **Parameter-set resolution:** each bound parameter narrows the current set mask to the sets it belongs to. After binding, with *one* valid set that set is chosen. With *several* valid sets: if the mask is \"all sets\" and the command has no default set, the call is accepted as set-less; else if the command defines a default set and it is among the valid sets, the command's parameter-set name is set to the default set, and the mask is narrowed to the default set only in validation calls that ask for it (the final check after command-line binding does; the checks made before dynamic parameters and during pipeline binding may not); else, if pipeline input is still expected and some valid set has an unbound parameter that takes pipeline input, the decision is postponed to pipeline binding; else the mask is reduced to sets with no unbound mandatory parameter; if exactly one set remains it is chosen, otherwise `AmbiguousParameterSet`. With *zero* valid sets (conflicting parameters) the result is `AmbiguousParameterSet` as well. **Pipeline-object binding** for each input object restores the saved mask and the original values of parameters bound by the previous object, then makes four passes over the unbound parameters that accept pipeline input \u2014 (a) by value without coercion, (b) by property name without coercion, (c) by value with coercion, (d) by property name with coercion \u2014 trying the default set before the other valid sets in each pass; a successful bind narrows the set mask again.",
"label": "FACT-SRC",
"evidence": [
"src/System.Management.Automation/engine/CmdletParameterBinderController.cs::CmdletParameterBinderController.BindCommandLineParametersNoValidation@L202-L277",
"src/System.Management.Automation/engine/ParameterBinderController.cs::ParameterBinderController.BindPositionalParameters@L699-L871",
"src/System.Management.Automation/engine/CmdletParameterBinderController.cs::CmdletParameterBinderController.ValidateParameterSets@L2532-L2640",
"src/System.Management.Automation/engine/CmdletParameterBinderController.cs::CmdletParameterBinderController.BindPipelineParametersPrivate@L3255-L3347",
"src/System.Management.Automation/engine/ParameterBinderBase.cs::ParameterBinderBase.BindParameter@L329-L667"
],
"owner": "03-runtime/parameter-binding.md",
"status": "open"
}
],
"deviations": [
{
"id": "DEV-BIND-130",
"baseline_behavior": "Execution-detail logging records bound values (first 256 characters) for every parameter.",
"proposed_behavior": "Redact bound values by parameter type and attribute (secure types, sensitive marker).",
"benefit": "Avoids leaking secrets into logs.",
"compatibility_cost": "Existing log consumers lose raw values.",
"affected_cfs": [
"CF-BND-001"
],
"status": "PROPOSED"
},
{
"id": "DEV-CMDLET-135",
"baseline_behavior": "Cmdlets can require a transaction (-UseTransaction, SupportsTransactions) via an engine protection scope.",
"proposed_behavior": "Omit transaction support.",
"benefit": "Removes a Windows-only feature and engine scope handling.",
"compatibility_cost": "Cmdlets and scripts using transactions are unsupported.",
"affected_cfs": [
"CF-LCY-001"
],
"status": "PROPOSED"
}
]
}
23 changes: 23 additions & 0 deletions docs-out/.work/cf/T34.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"cfs": [],
"deviations": [
{
"id": "DEV-PROV-140",
"baseline_behavior": "Providers receive a mutable Context set by the engine and have no policy mediation layer.",
"proposed_behavior": "A mandatory policy mediation layer between engine and providers and an explicit per-call context object.",
"benefit": "Root confinement, rights and audit enforced outside provider code.",
"compatibility_cost": "Provider authors must target a new context type.",
"affected_cfs": [],
"status": "PROPOSED"
},
{
"id": "DEV-PROV-141",
"baseline_behavior": "File-system drives are auto-mounted on lookup miss.",
"proposed_behavior": "Mount drives explicitly or from configuration.",
"benefit": "Predictable drive table; no hidden system probing.",
"compatibility_cost": "Scripts using unmounted drive letters need explicit mounts.",
"affected_cfs": [],
"status": "PROPOSED"
}
]
}
42 changes: 42 additions & 0 deletions docs-out/.work/cf/T35.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"cfs": [
{
"id": "CF-ETS-001",
"subject": "member resolution order",
"statement": "**Member resolution order (CF-ETS-001).** Looking up member *name* on a value `v` (wrapped as a `PSObject`) proceeds in this order and returns the first hit: (1) the reserved names `psbase`, `psadapted`, `psextended`, `psobject` and `pstypenames`, generated on demand; (2) **instance members** added to this object (for example by `Add-Member`); (3) **type-table (extended) members** merged over the object's type-name hierarchy, most specific type name winning; (4) **adapted members** from the adapter chosen for the object; (5) **base members**: the .NET members of the wrapped object, only when the chosen adapter is not already the .NET adapter. Member-name matching in the .NET adapter is case-insensitive (its binding flags include `IgnoreCase`). Type-table collection entries are marked \"replicate and clone when returning\" (a copy bound to the current object is handed out), adapted and base entries are not; the enumeration order across sources is `UNVERIFIED` (VB-038). Member lookup on a `PSMemberSet` owner searches the set's own members first, then the same collections.",
"label": "FACT-SRC",
"evidence": [
"src/System.Management.Automation/engine/MshMemberInfo.cs::PSMemberInfoIntegratingCollection@L4503-L5152",
"src/System.Management.Automation/engine/MshObject.cs::PSObject.GetMappedAdapter@L460-L538",
"src/System.Management.Automation/engine/TypeTable.cs::TypeTable.MemberFactory@L3985-L4041",
"src/System.Management.Automation/engine/MshObject.cs::PSObject.GetMemberCollection@L261-L309"
],
"owner": "03-runtime/extended-type-system.md",
"status": "open"
}
],
"deviations": [
{
"id": "DEV-ETS-150",
"baseline_behavior": "Adapters exist for WMI, DirectoryEntry, DataRow/DataRowView, COM, CIM and XML nodes.",
"proposed_behavior": "Ship .NET, XML, PSObject, member-set and the third-party adapter bridge only.",
"benefit": "Smaller surface, fewer Windows-only dependencies.",
"compatibility_cost": "Scripts using those object kinds lose adapted members.",
"affected_cfs": [
"CF-ETS-001"
],
"status": "PROPOSED"
},
{
"id": "DEV-ETS-151",
"baseline_behavior": "Built-in type data is compiled into C# from types.ps1xml.",
"proposed_behavior": "Compile at build time and also publish a versioned data file.",
"benefit": "One source for tooling and a clean-room implementation.",
"compatibility_cost": "None observable.",
"affected_cfs": [
"CF-ETS-001"
],
"status": "PROPOSED"
}
]
}
Loading
Loading