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
19 changes: 9 additions & 10 deletions .github/workflows/publish_nuget.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,21 +80,20 @@ jobs:
- name: "Extract latest release notes"
shell: pwsh
run: |
# RELEASE_NOTES.md uses `#### X.Y.Z[-suffix] <date> ####` per-section
# headings. Capture only the BODY of the first section (no heading)
# so the GitHub release page doesn't duplicate the version string in
# both the title and the first line of the body, and so a stale
# hand-typed date in the heading doesn't fight the published date
# GitHub renders automatically.
# Select the pushed version, not the first section. An Unreleased
# section can remain at the top without changing the published body.
if (-not (Test-Path RELEASE_NOTES.md)) {
"No release notes available." | Set-Content RELEASE_NOTES_LATEST.md
exit 0
Write-Error "RELEASE_NOTES.md does not exist."
exit 1
}
$content = Get-Content RELEASE_NOTES.md -Raw
if ($content -match '(?s)####[^\r\n]*\r?\n+(.+?)(?=\r?\n####|\z)') {
$version = [regex]::Escape($env:PACKAGE_VERSION)
$pattern = "(?ms)^####\s+$version(?=\s|#|\r?$)[^\r\n]*\r?\n+(.+?)(?=^####|\z)"
if ($content -match $pattern) {
$Matches[1].Trim() | Set-Content RELEASE_NOTES_LATEST.md
} else {
$content | Set-Content RELEASE_NOTES_LATEST.md
Write-Error "RELEASE_NOTES.md has no section for $env:PACKAGE_VERSION."
exit 1
}

- name: "Create GitHub release"
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,5 +203,5 @@ dotnet test -c Release
dotnet pack -c Release -o ./bin/nuget

# Cut a release (manual, then push the tag)
git tag v0.1.0-alpha && git push origin v0.1.0-alpha
git tag 0.3.0-alpha && git push origin 0.3.0-alpha
```
3 changes: 2 additions & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<VersionPrefix>0.2.0</VersionPrefix>
<VersionPrefix>0.3.0</VersionPrefix>
<VersionSuffix>alpha</VersionSuffix>
</PropertyGroup>
<PropertyGroup>
<!-- Target framework matrix -->
Expand Down
4 changes: 4 additions & 0 deletions IMPLEMENTATION_PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,10 @@ priorities.
set does not support `-AsJob`.
- [ ] Complete the stable-v0.3 Bash `for ... in` and PowerShell `foreach`
vertical slices without gating release on a shared-analysis refactor.
- [ ] Publish `0.3.0-alpha` for the Netclaw migration gate. The release branch
sets matching package metadata, release notes, and the bare SemVer tag
contract. Mark this complete only after the tag workflow publishes the
package and GitHub prerelease.
- [ ] Build on the delivered bounded Bash heredoc grammar and quoted-delimiter
adjacency by exposing public body/delimiter/expansion/completeness facts,
then add a separately tested Bash `<<<` here-string redirect slice.
Expand Down
29 changes: 29 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,34 @@
#### Unreleased ####

#### 0.3.0-alpha 2026-08-08 ####

This prerelease exposes the v0.3 structured-analysis API for Netclaw
integration. It keeps the v0.2 compatibility projection for existing
consumers. Unknown or unsupported forms continue to fail closed.

## Added

- Added `ParsedCommand.Syntax` and `ParsedCommand.Commands`. Consumers can now
inspect every supported command occurrence in nested shell structure.
- Added typed syntax nodes, occurrence roles, ancestry, completeness facts,
value domains, and explicit redirect analysis.
- Added bounded Bash `for ... in` and PowerShell `foreach` analysis. Exact and
finite loop values require the documented isolated initial-state modes.
- Added command-substitution and PowerShell execution-region discovery for the
supported v0.3 grammar.
- Added explicit file, stream, and descriptor redirect facts. Static descriptor
operations no longer require a consumer to infer safety from raw text.

## Compatibility and security

- Kept all v0.2 `ParsedCommand.Clauses`, `Clause`, `Arg`, and `Redirect`
members. The compatibility projection remains conservative.
- Kept incomplete occurrences, unknown values, dynamic command identities,
and unsupported execution-bearing syntax fail closed.
- The corpus now contains 268 Bash cases and 417 PowerShell cases. Both corpora
pass the PII audit. Every PowerShell input has a real-`pwsh` parse check,
and targeted real-Bash tests pin supported Bash semantics.

#### 0.2.0 2026-08-05 ####

This stable release includes all behavior and API surface from the
Expand Down
7 changes: 4 additions & 3 deletions SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -2451,7 +2451,8 @@ The repo template already has:

Adapt for ShellSyntaxTree:

- **Trigger NuGet publish on tag pattern `v*.*.*`** (e.g. `v0.1.0-alpha`).
- **Trigger NuGet publish on a bare SemVer tag** (for example,
`0.3.0-alpha`). A leading `v` is invalid.
- **Test job** runs the corpus runner plus all unit tests.
- **PII audit job** runs the sanitization-pattern scan over `tests/ShellSyntaxTree.Tests/Corpus/`.

Expand Down Expand Up @@ -2521,7 +2522,7 @@ A natural order for the implementer:
covering each section. Iterate parser to make all pass.
13. **Sanitize and seed from real logs** (§14) — script + manual review.
Add 50-100 more corpus entries.
14. **Wire CI** (§15). Tag v0.1.0-alpha when corpus is green and PII audit
14. **Wire CI** (§15). Tag `0.1.0-alpha` when the corpus is green and the PII audit
passes.

Estimated implementation effort: 600-800 LOC of source + 400-600 LOC of
Expand All @@ -2544,7 +2545,7 @@ v0.1.0-alpha ships when **all** of the following hold:
3. ✅ Corpus has at least 105 entries spanning the categories in §13.
4. ✅ PII audit scan over `tests/ShellSyntaxTree.Tests/Corpus/bash/*.json` finds zero hits.
5. ✅ `dotnet test` runs on PR via GitHub Actions and passes.
6. ✅ Tagging `v0.1.0-alpha` triggers `publish_nuget.yml` and the package
6. ✅ Tagging `0.1.0-alpha` triggers `publish_nuget.yml` and the package
appears on nuget.org.
7. ✅ Netclaw can consume the package via `<PackageReference>` and the
`IShellParser` resolves at runtime in Netclaw's DI container.
Expand Down
6 changes: 3 additions & 3 deletions TOOLING.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ checked-in corpus.
|---|---|---|
| `git` | shell | everything |
| `gh` CLI | shell | issues, PRs, releases, tag pushes |
| GitHub Actions | `.github/workflows/` | `pr_validation.yml` (build + test + pack on PR/push), `publish_nuget.yml` (pack + push + release on `v*.*.*` tags) |
| GitHub Actions | `.github/workflows/` | `pr_validation.yml` (build + test + pack on PR/push), `publish_nuget.yml` (validates bare SemVer tags, then packs, pushes, and releases) |
| GitHub Dependabot | `.github/dependabot.yml` | NuGet bumps |

## NuGet
Expand Down Expand Up @@ -97,8 +97,8 @@ Required configuration (one-time, on `nuget.org`):
Required configuration (one-time, in repo settings):

1. **Settings → Environments → New environment** → name `nuget`.
Optional protection: restrict deployment to tags matching
`v*.*.*`.
Optional protection: restrict deployment to bare SemVer release tags such
as `0.3.0-alpha`.
2. **Settings → Secrets and variables → Actions → New repository
secret** — `NUGET_USER` set to the nuget.org account username
that owns the package. The legacy `NUGET_KEY` secret can be
Expand Down