Skip to content
Merged
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
13 changes: 11 additions & 2 deletions IMPLEMENTATION_PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,9 +240,15 @@ priorities.
`Clause` identity; unsupported wrapper tails and depth overflow fail
closed. Redirect-bearing leaves remain incomplete until the explicit
redirect-analysis slice lands.
- [ ] Adapt the existing PowerShell grammar to emit the structural and
- [x] Adapt the existing PowerShell grammar to emit the structural and
command-occurrence projections before enabling any control-flow
construct.
construct. The PowerShell-specific recursive coordinator preserves
statement/pipeline precedence, current-scope parenthesized groups,
isolated child-host wrappers, current-scope `Invoke-Expression`, exact
direct spans, nullable decoded spans, compatibility operators, and
shared leaf identity. It rejects hostile structural depth before descent
and leaves redirects, dynamic identities, unproved host command strings,
and undiscovered executable expressions incomplete.
- [ ] Deliver paired Bash and PowerShell `$()` substitution slices for all
locked executable value positions, including ordering, ancestry,
shell-specific cwd propagation, literal/escaped boundaries, dynamic
Expand All @@ -266,6 +272,9 @@ priorities.

- Seed corpus entries from sanitized real-world dogfood logs (SPEC §14
workflow) — both shells.
- Synchronize PowerShell corpus manifest entries 282–309 before using the
generator as an all-corpus rewrite; until then, targeted manifest changes
must preserve the checked-in hand-authored tail.
- Expand verb / cmdlet / alias tables as the corpus surfaces real commands.
- Performance sanity check (~1 ms typical) with a tiny BenchmarkDotNet
harness — only if anything in the daemon hot path complains.
Expand Down
14 changes: 14 additions & 0 deletions SPEC.POWERSHELL.md
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,11 @@ quoted_string := single_quoted | double_quoted
arguments is a syntax error and makes the whole result unparseable.
- A parenthesized **pipeline** `( ... )` parses as a grouped sub-pipeline;
its clauses carry `IsSubshell = true` as a *structural* marker only.
PowerShell permits that grouped expression only as the first pipeline
element; `Get-Date | (Get-Process)` is unparseable rather than a second
grouped stage. The group body is one pipeline, so statement separators such
as `(Get-Date; Get-Process)` are also unparseable. Leading and trailing
newlines inside the delimiters collapse.
Unlike a bash subshell, PowerShell's `( ... )` is a grouping operator — it
creates **no scope and no working-directory boundary** (`$PWD` is runspace
state, not a scoped variable). `Set-Location` attribution therefore
Expand Down Expand Up @@ -1100,6 +1105,15 @@ inner clause's `Redirects` and `Elements`; its outer source span remains exact.
Non-redirect arguments after a quoted, script-block, colon-bound, or encoded
payload are not modeled and set `IsUnparseable=true` rather than disappearing.

When the complete command-string production is not proved, the parser retains
the authored outer host clause but sets its command occurrence
`IsComplete=false`. This includes dynamic or quoted wrapper-control input,
`--%`, stdin-driven `-Command -`, and command-string-capable forms outside the
locked grammar such as `-CommandWithArgs` / `-cwa`. The same incomplete-outer
rule applies to a computed `Invoke-Expression` payload. These leaves preserve
compatibility evidence; they are never sufficient authorization evidence and
must not be mistaken for proof that no hidden command can execute.

`pwsh -File script.ps1` is **not** recursion — the file content is not
available to the parser. It parses as an ordinary clause with `script.ps1`
as a path arg.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,16 @@ partial command and compatibility result.
- **THEN** the existing outer compatibility leaf remains visible with direct source provenance
- **THEN** its command occurrence has `IsComplete=false` because no hidden command-string body was discovered

#### Scenario: Unproved PowerShell command string remains incomplete
- **WHEN** PowerShell parses a `pwsh` or `powershell` host whose command-string control is dynamic, quoted, hidden behind `--%`, stdin-driven by `-Command -`, or uses an unsupported command-string-capable form such as `-CommandWithArgs` / `-cwa`
- **THEN** the existing outer compatibility leaf remains visible with direct source provenance
- **THEN** its command occurrence has `IsComplete=false` because no complete executable body was discovered

#### Scenario: Computed Invoke-Expression remains incomplete
- **WHEN** PowerShell retains an outer `Invoke-Expression` clause because its payload is computed rather than one exact static scalar
- **THEN** the payload remains an authored `DynamicSkip` value
- **THEN** the command occurrence has `IsComplete=false` and cannot authorize hidden code

#### Scenario: While condition and body roles
- **WHEN** Bash parses `while curl URL; do sleep 1; done`
- **THEN** `curl` is identified as a condition occurrence
Expand Down
4 changes: 2 additions & 2 deletions openspec/changes/v0-3-structured-shell-analysis/tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
- [x] 3.4 Build a library-owned traversal that emits each simple command occurrence exactly once in deterministic source order.
- [x] 3.5 Build the conservative `Clauses` compatibility flattener without inventing cross-structure compound operators.
- [x] 3.6 Adapt the existing Bash grammar to emit the structural model with no newly supported syntax.
- [ ] 3.7 Adapt the existing PowerShell grammar to emit the structural model with no newly supported syntax.
- [ ] 3.8 Add tests proving existing parser inputs retain their v0.2 leaf and compatibility results.
- [x] 3.7 Adapt the existing PowerShell grammar to emit the structural model with no newly supported syntax.
- [x] 3.8 Add tests proving existing parser inputs retain their v0.2 leaf and compatibility results, except for explicitly promoted v0.3 fail-closed cases.
- [ ] 3.9 Add corpus expectations for syntax shape, occurrences, roles, and completeness for existing constructs.
- [ ] 3.10 Implement Bash `$()` discovery in supported argument words, redirect values, iterables, and expanding heredoc bodies; retain literal/escaped spellings and fail closed on command-name substitutions, legacy backticks, or incomplete interiors.
- [ ] 3.11 Implement PowerShell `$()` discovery in supported words, redirect values, foreach expressions, call-operator dynamic identities, standalone expression statements, double-quoted strings, and expandable here-strings; never invent invocation from standalone output, retain literal/escaped spellings, and fail closed on trailing command-style arguments, call-operator script blocks, or unsupported execution-bearing `@()` / `@{}` forms.
Expand Down
Loading