Skip to content

feat(samples): CLI explainer/auditor + Blazor WASM Mermaid visualizer#12

Merged
Aaronontheweb merged 1 commit into
devfrom
feat/samples-and-readme
May 10, 2026
Merged

feat(samples): CLI explainer/auditor + Blazor WASM Mermaid visualizer#12
Aaronontheweb merged 1 commit into
devfrom
feat/samples-and-readme

Conversation

@Aaronontheweb

Copy link
Copy Markdown
Owner

Summary

Two runnable samples demonstrating the ShellSyntaxTree v0.1.0-alpha API, plus a complete README rewrite for end-user consumption.

What landed

samples/ShellSyntaxTree.Cli.Sample (net8.0 console)

System.CommandLine 2.0.7. Two subcommands:

```bash
dotnet run --project samples/ShellSyntaxTree.Cli.Sample -- explain "cd /repo && rm /etc/passwd"
dotnet run --project samples/ShellSyntaxTree.Cli.Sample -- audit "cd /repo && rm /etc/passwd"
```

  • `explain` — pretty-prints the AST with [flag] / [path] / [cwd-attr] / [dyn-skip] / [glob] markers, redirect targets, IsSubshell / IsBashCWrapped flags. `IsUnparseable` shows reason.
  • `audit` — built-in policy: deny writes under /etc///usr///bin///sbin///lib/; warn on curl | bash; warn on dynamic args in path slots; warn on unparseable. Exits 0/1/2 by severity. AuditPolicy.cs is one file so the README can point at it.

samples/ShellSyntaxTree.Web.Sample (net8.0 Blazor WASM)

Paste a bash script → see the parsed AST as a Mermaid flowchart. Everything runs in the browser. mermaid.js v11 from jsDelivr CDN; JS interop via a 30-line wrapper. 300ms debounced auto-render. Five preset buttons cover compound commands, subshell isolation, bash -c recursion, dynamic-cwd attribution, and unparseable inputs. Source / AST / Unparseable tabs alongside the diagram.

```bash
dotnet run --project samples/ShellSyntaxTree.Web.Sample

http://localhost:5239

```

Validated end-to-end via Playwright; 8 screenshots saved to assets/sample-web-*.png and referenced from the README.

README rewrite

Out: the Akka-template-flavored sections (status, why-not-tree-sitter, repository layout). In:

  • Elevator pitch + install line at top
  • Inline mermaid example (GitHub renders directly in the README)
  • Use-case bullets — AI agent gates, CI/CD audits, sandbox policy, pre-commit linters, audit-log analytics, documentation
  • Quick-start consumer code (~25 LOC)
  • Pointer to both samples with copy-pasteable invocations
  • Locked v0.1 public API summary
  • Versioning + license + repo-layout table

Renderer fixes after Playwright validation

  • Empty input now returns empty mermaid source so the host page shows its placeholder instead of a phantom "(no commands)" node
  • 2>&1 and similar fd-dup redirect targets no longer render as fake file nodes (basename & check handles the resolver's cwd-joined form)
  • Apostrophes in mermaid node labels left unescaped (mermaid 11 renders ' as literal &' inside ["..."] labels)
  • Node labels fall back to first non-flag arg when no paths are present (so echo done, set -e render with their args)
  • Razor textarea placeholder was double-encoding &&

What's unchanged

  • Public API surface — PublicApiSnapshotTests still 18/18 green
  • Test count — still 353/353 passing
  • CI workflows — no new files; samples deliberately not deployed to Pages
  • Library project / packaging — samples are IsPackable=false

CPM additions

  • System.CommandLine 2.0.7
  • $(AspNetCoreVersion) = 8.0.26 for Microsoft.AspNetCore.Components.WebAssembly[.DevServer]

Test plan

  • CI passes on `Test-ubuntu-latest`
  • CI passes on `Test-windows-latest`
  • README mermaid block renders correctly in GitHub UI (visual check after merge)
  • `dotnet run --project samples/ShellSyntaxTree.Web.Sample` boots and the Build-script preset renders

Adds two runnable samples that demonstrate consuming the ShellSyntaxTree
v0.1.0-alpha API. Both samples are IsPackable=false so they don't ship
in the nupkg.

samples/ShellSyntaxTree.Cli.Sample (net8.0 console, System.CommandLine 2.0.7):
- `explain "<cmd>"` — pretty-prints the AST with [flag]/[path]/
  [cwd-attr]/[dyn-skip]/[glob] markers per arg, redirect targets, and
  the IsSubshell/IsBashCWrapped flags. Unparseable inputs show the
  reason.
- `audit "<cmd>"` — runs a tiny built-in policy (deny writes under
  /etc/, /usr/, /bin/, /sbin/, /lib/; warn on `curl | bash`; warn on
  dynamic content in path-arg slots; warn on IsUnparseable). Exits
  0/1/2 by severity.
- AuditPolicy.cs is one file so the README can point at it as a
  reference implementation.

samples/ShellSyntaxTree.Web.Sample (net8.0 Blazor WebAssembly):
- Single page: textarea on the left, mermaid SVG render on the right.
- Five preset buttons covering compound commands, subshell isolation,
  bash -c recursion, dynamic-cwd attribution, and unparseable inputs.
- Source/AST/Unparseable tabs alongside the rendered diagram.
- 300ms debounced auto-render on input; Render button available too.
- mermaid.js v11 loaded from jsDelivr CDN; JS interop via
  shellSyntaxTreeInterop.renderMermaid().
- MermaidRenderer.cs handles label escaping, subshell/bash -c
  subgraphs, dotted edges for redirects, and CSS classes for
  unparseable (red) and dynamic-skip (yellow) nodes.
- ScriptSplitter.cs folds line continuations, skips blank/comment
  lines, preserves heredoc bodies so the parser sees them whole.

README rewritten:
- Elevator pitch + install line up top
- Inline mermaid example (GitHub renders directly)
- Use-case bullets covering AI agent gates, CI/CD audits, sandbox
  policy generation, pre-commit linters, audit-log analytics, and
  documentation tools
- Quick-start code snippet (~25 LOC of consumer code)
- Pointer to both samples with copy-pasteable `dotnet run` commands
- Repository layout table for contributors
- Locked public API surface from SPEC §2

Eight screenshots captured via Playwright validating the Blazor sample's
core scenarios (empty state, build script, subshell, bash -c,
unparseable, dynamic cwd, custom input, source tab).

Renderer fixes after first Playwright pass:
- Empty input now returns string.Empty so the host page's "No script
  yet" placeholder shows instead of a phantom "(no commands)" node.
- `2>&1` and `N>&M` fd-dup redirect targets are filtered out (they're
  not files; basename-startswith-& check handles the resolver's
  cwd-joined form like `/work/&1`).
- Apostrophes in node labels left unescaped (mermaid 11 renders
  &#39; as `&'` inside `["..."]` labels).
- Node labels fall back to first non-flag arg when no path args are
  present, so verbs like `echo done` and `set -e` show their args
  instead of rendering as bare verb-only nodes.
- Razor textarea placeholder was Razor-encoding && to &amp;&amp;.

API surface unchanged; tests still 353/353.

CPM additions:
- System.CommandLine 2.0.7
- $(AspNetCoreVersion) = 8.0.26 for Microsoft.AspNetCore.Components.WebAssembly[.DevServer]

No new CI/CD workflow. Samples runnable via `dotnet run` only.
@Aaronontheweb Aaronontheweb enabled auto-merge (squash) May 10, 2026 21:13
@Aaronontheweb Aaronontheweb merged commit dcba0b4 into dev May 10, 2026
2 checks passed
@Aaronontheweb Aaronontheweb deleted the feat/samples-and-readme branch May 10, 2026 21:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant