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
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<VersionPrefix>0.4.0</VersionPrefix>
<VersionSuffix>beta.2</VersionSuffix>
<VersionSuffix>beta.3</VersionSuffix>
</PropertyGroup>
<PropertyGroup>
<!-- Target framework matrix -->
Expand Down
7 changes: 7 additions & 0 deletions IMPLEMENTATION_PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ priorities.

---

## NOW (0.4.0-beta.3 finite Bash scopes)

- [x] Define an additive public scope result in `SPEC.md`.
- [x] Prove exact directories and reparse each authored simple command under every reachable scope.
- [x] Run Release tests, the public API contract, the corpus PII audit, the header check, and package checks.
- [ ] Merge the PR after Linux and Windows CI. Tag `0.4.0-beta.3` and verify NuGet publication.

## NOW (0.3.4 working-directory effects and downstream acceptance)

- [x] **Create the v0.3.1 approval-fact OpenSpec.** Harvest and sanitize the
Expand Down
16 changes: 16 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
#### 0.4.0-beta.3 2026-09-17 ####

This prerelease adds bounded Bash directory facts for complete static compounds.

## Added

- Add `BashParser.TryProjectFiniteScopes` and parser-owned scoped occurrences.
- Preserve exact path facts for each reachable directory after `&&`, `||`, and `;`.
- Preserve both success and failure directories after an exact `cd` target.

## Security and compatibility

- Reject unknown directory effects, nested execution, changed source slices, and excess scopes.
- Keep dynamic operands unknown inside an exact directory.
- Preserve the existing parser result and public methods. The new API grants no authority.

#### 0.4.0-beta.2 2026-09-14 ####

This maintenance prerelease publishes the post-beta.1 PowerShell approval
Expand Down
67 changes: 67 additions & 0 deletions SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ public sealed class BashParser : IShellParser
public BashParser();
public BashParser(BashParserOptions options);
public ParsedCommand Parse(string command);
public bool TryProjectFiniteScopes(
string command,
out BashFiniteScopeProjection? projection);
}

/// <summary>PowerShell implementation of IShellParser (v0.2.0). The
Expand Down Expand Up @@ -239,6 +242,10 @@ public enum HereDocumentExpansionMode { ... }
// v0.4 authored-list and tree-access evidence — see §3.
public sealed record ShellFileSystemTreeAccess { ... }
public enum ShellTreeTraversalMode { ... }

// v0.4.0-beta.3 finite Bash scope evidence — see §3.
public sealed record BashFiniteScopeProjection { ... }
public sealed record BashScopedCommand { ... }
```

Stable v0.3 exposes only structural types the parsers can emit. The additive
Expand All @@ -248,6 +255,8 @@ package. Condition-loop and branch grammar remains
fail closed and reserves no public type or enum member. Every result type added
since v0.2 is parser-owned; its constructor and result setters are not public.
The stable v0.2 constructors and setters are unchanged.
The finite Bash scope method and result records target `0.4.0-beta.3`.
They add no authority rule and do not change an existing occurrence.

That's the entire public API. **Everything else is internal.** The lexer,
parser internals, verb tables, resolver — all implementation detail.
Expand Down Expand Up @@ -299,6 +308,25 @@ public sealed record ParsedCommand
}
```

`TryProjectFiniteScopes` returns these parser-owned records:

```csharp
public sealed record BashFiniteScopeProjection
{
public ParsedCommand Parsed { get; internal init; }
public IReadOnlyList<BashScopedCommand> Commands { get; internal init; }
}

public sealed record BashScopedCommand
{
public CommandOccurrence SourceOccurrence { get; internal init; }
public CommandOccurrence ScopedOccurrence { get; internal init; }
public string Source { get; internal init; }
public int SourceStart { get; internal init; }
public string WorkingDirectory { get; internal init; }
}
```

`WindowsPowerShell51` uses separately oracle-pinned grammar and metadata. Its
command-owned execution-region catalog is limited to Windows PowerShell
`5.1.19041.6456` `ForEach-Object` Begin/Process/RemainingScripts/End and
Expand Down Expand Up @@ -791,6 +819,45 @@ destination. Any other domain, malformed set, over-limit join, or missing fact
makes the whole public effect `Unknown`. A target does not prove existence,
accessibility, authorization, or runtime success.

#### Finite Bash scope projection (v0.4.0-beta.3)

`BashParser.TryProjectFiniteScopes` parses the full source and proves each
reachable exact directory for a bounded static top-level command list.
It returns `false` and a null result if it cannot complete the proof.
The result owns the full `ParsedCommand` and ordered `BashScopedCommand` records.
Records follow list-item order, ordinal directory order within an item, and
pipeline-stage order within a directory.
Each record identifies the original occurrence, its exact source slice and
offset, one reachable directory, and a fresh occurrence parsed in that directory.
The fresh occurrence supplies its own argument, redirect, and tree-access path
facts. Unknown path facts remain unknown; an exact directory does not make a
dynamic operand exact.

The projection uses this schematic flow:

```text
entry = initial exact directory
for each top-level list item:
choose entry directories from prior success, failure, or both
parse every simple command under each entry directory
reject nested execution and an unknown directory effect
keep the entry directory after failure
use the exact target after a successful directory change
preserve both outcomes at a sequence boundary
```

Each pipeline stage receives the same entry directory. A pipeline stage with
a directory effect other than `Unchanged` makes the projection fail.
The result includes each reachable directory, even when a directory change can
fail. The proof stops above 32 directories or 128 scoped occurrences.
It also stops on unknown effects, nested execution, incomplete occurrences,
source-span mismatch, or unsupported list structure.

For example, `cd /work/sub && true; touch marker.txt` from `/work` yields
`touch` under both `/work` and `/work/sub`. Its path facts name both possible
files. By contrast, `cd "$target" && touch marker.txt` yields no projection.
The caller owns filesystem checks, policy, grant matching, and process launch.

Effects join per authored occurrence. Two `Unchanged` visits remain
`Unchanged`; two success-only changes join their bounded targets. Unknown,
mixed unchanged/change visits, missing visits, or lost correlation join to
Expand Down
Loading