Skip to content

chore: bootstrap ShellSyntaxTree from Akka template#3

Merged
Aaronontheweb merged 1 commit into
devfrom
chore/bootstrap-shellsyntaxtree-agent-os
May 10, 2026
Merged

chore: bootstrap ShellSyntaxTree from Akka template#3
Aaronontheweb merged 1 commit into
devfrom
chore/bootstrap-shellsyntaxtree-agent-os

Conversation

@Aaronontheweb

Copy link
Copy Markdown
Owner

Summary

  • Strip the inherited Akka.NET build-system-template artifacts (.azure/, Akka.Console sample, akkalogo.png, build.ps1 + release-notes scripts, DocFX local tool, Akka.Hosting / Microsoft.Extensions.Hosting package refs, Akka.Event global Using).
  • Rewrite repo metadata for ShellSyntaxTree under Aaron Stannard attribution: Directory.Build.props, Directory.Packages.props (xUnit + test SDK + coverlet via Central Package Management), README.md, ShellSyntaxTree.slnx (renamed from SampleSln.slnx).
  • Land the agent operating system: PROJECT_CONTEXT.md, TOOLING.md, AGENTS.md (thin constitution with MODE=build/corpus/release routing), IMPLEMENTATION_PLAN.md (NOW / NEXT / LATER from SPEC.md §16), and SPEC.md (the locked v0.1 contract). CLAUDE.md is a symlink to AGENTS.md.
  • Update CI: pr_validation.yml runs build/test/pack and verifies copyright headers; publish_nuget.yml triggers on v*.*.* tags and computes the package version from the tag.
  • Port the Netclaw copyright-header script (scripts/Add-FileHeaders.ps1) under Aaron Stannard attribution, covering src/ and tests/. CI runs -Verify.
  • Generate and commit a NuGet package icon (assets/icon.png, 512x512, AST motif on dark background) wired in via PackageIcon.

Test plan

  • dotnet tool restore succeeds (DocFX removed; incrementalist only)
  • dotnet restore against ShellSyntaxTree.slnx resolves with no Akka package references
  • dotnet build -c Release succeeds (no projects yet, no source — should be a clean no-op)
  • pwsh ./scripts/Add-FileHeaders.ps1 -Verify exits 0
  • pr_validation.yml passes on both ubuntu-latest and windows-latest
  • Directory.Build.props PackageIcon=icon.png resolves once the first project lands and dotnet pack runs

Notes

  • CLAUDE.md is committed as a symlink (mode 120000) pointing at AGENTS.md. On Linux/macOS this is transparent; Windows clones need git config --global core.symlinks true to materialize the link rather than treat it as a 9-byte text file.
  • No source projects yet — implementation begins on a follow-up branch per IMPLEMENTATION_PLAN.md NOW item Bump AButler/upload-release-assets from 3.0 to 4.0 #1.

Strip inherited Akka.NET build-system-template artifacts and stand up
the agent operating system for the ShellSyntaxTree library:

- Remove `.azure/`, `src/Akka.Console/`, `akkalogo.png`, `build.ps1`,
  legacy release-notes PowerShell, DocFX local tool, Akka.Hosting and
  Microsoft.Extensions.Hosting package references, Akka.Event global
  Using.
- Rewrite `Directory.Build.props` and `Directory.Packages.props` for
  Aaron Stannard attribution, ShellSyntaxTree NuGet metadata, xUnit
  test stack, and SourceLink. `VersionPrefix=0.1.0`,
  `VersionSuffix=alpha`.
- Rename `SampleSln.slnx` to `ShellSyntaxTree.slnx`; rewrite README
  to describe the library rather than the build template.
- Update CI: `pr_validation.yml` runs build/test/pack and verifies
  copyright headers; `publish_nuget.yml` triggers on `v*.*.*` tags
  and computes the package version from the tag.
- Add agent OS files: `PROJECT_CONTEXT.md`, `TOOLING.md`, `AGENTS.md`,
  `IMPLEMENTATION_PLAN.md`. `CLAUDE.md` is a symlink to `AGENTS.md`.
- Add `SPEC.md` (the locked v0.1 contract).
- Add `scripts/Add-FileHeaders.ps1` (Aaron Stannard copyright header
  enforcement, modeled on the Netclaw equivalent) covering `src/` and
  `tests/`. CI runs `-Verify`.
- Generate and commit a NuGet package icon (`assets/icon.png`,
  512x512) wired into `Directory.Build.props` via `PackageIcon`.
@Aaronontheweb
Aaronontheweb merged commit a0770f5 into dev May 10, 2026
2 checks passed
@Aaronontheweb
Aaronontheweb deleted the chore/bootstrap-shellsyntaxtree-agent-os branch May 10, 2026 15:55
Aaronontheweb added a commit that referenced this pull request May 10, 2026
* PR 4: BashResolver + per-verb path rules + flag-aware verb probe

Implements SPEC §8 (resolver) and SPEC §7 (per-verb path-arg rules) +
the flag-with-value-aware verb-chain probe deferred from PR 3. Locked
interpretations #3 (Glob vs DynamicSkip distinction) and #8 (tar /
docker -v default rule) materialized.

What's wired:
- Internal/Resolving/BashResolver.cs (SPEC §8 pipeline):
  * filesystem:: prefix strip
  * tilde + $HOME expansion (HomeDirectory lazy fallback to
    Environment.SpecialFolder.UserProfile)
  * other $VAR/${VAR} in path slot → Kind=DynamicSkip, IsPath=false
  * other $VAR in non-path slot → Kind=EnvVar
  * glob detection: Kind=Glob, IsPath=true in path slot (covering-dir
    heuristic preserved per locked #3)
  * relative-path join against WorkingDirectory (lazy fallback to
    Environment.CurrentDirectory)
  * LooksLikePath heuristic with curated extension list
  * IOException / path-format exception → DynamicSkip per SPEC §8 step 6

- Internal/Bash/Verbs/BashPerVerbRules.cs (SPEC §7):
  * Per-positional rules: chmod (mode/path), chown (user/path), chgrp
    (group/path), ln (all paths), find (path/predicates), grep/rg
    (pattern/paths), sed/awk (script/paths), tar (default rule per #8),
    curl/wget (URL not path; -o/-O values are paths), scp/rsync/sftp
    (all paths), cd-family (target path)
  * Default rule for FileVerbs without override: all non-flag
    positionals are paths
  * LooksLikePath fallback for non-FileVerbs
  * Flag-value path classification: git -C / --git-dir is path;
    curl -d/--data is body data not path; docker -v is single literal
    IsPath=false per locked #8; tar -f/-C are paths

- BashCommandParser updates:
  * Flag-with-value-aware verb-chain probe — `git -C /repo log` →
    Verb.Tokens=["git", "log"] per SPEC §12 example (deferred from PR 3)
  * Resolver wired into Arg construction
  * Redirect.Target = Resolved when resolvable; IsDynamicSkip=true
    otherwise

Tests:
- BashResolverTests: 34 tests covering tilde/$HOME/env-var/glob/
  filesystem::/abs/rel/LooksLikePath
- BashPerVerbRulesTests: 34 tests covering each per-verb rule + flag-
  value classification
- BashCommandParserTests: 9 new tests + refresh of PR 3 tests with
  HomeDirectory=/home/test, WorkingDirectory=/work
- 12 existing corpus entries refreshed for path classification
- 20 new corpus entries (51-70):
  * 51-60 dynamic-skip: $UNRESOLVED/foo, $REPO patterns, $HOME expansion,
    $LOG_FILE, ${PATH}/bin/foo, glob in path slot
  * 61-70 per-verb rules: chmod 755 path, chown user:group path, find
    /var/log -name "*.log", grep pattern path, sed script path, awk
    program path, curl -o path URL, wget -O path URL, git -C /repo log,
    tar -xf archive target

Total tests: 296/296 passing. Public API surface unchanged.

SPEC.md §8 updated:
- Step 4 explicitly states Glob has IsPath=true in path-arg slot and
  IsPath=false elsewhere; preserves covering-dir heuristic
- Step 6 narrows DynamicSkip to env-var-in-path-slot and resolver-throws
  cases (no longer overlaps with Glob)
- Glob and DynamicSkip carry distinct signals per locked #3

PR 4 → PR 5 follow-ups tracked in tasks.md:
- Subshell IsSubshell flag wiring (Segment.FromSubshell plumbed but
  unused)
- cd-attribution propagation via internal-context-state piggybacked on
  parsing pipeline
- locked #6 (cd $VAR propagation) DynamicSkip cwd signal

* Fix(resolver): produce bash-style paths on Windows

Path.GetFullPath is platform-aware. On Windows it expands `/etc/hosts`
to `D:\etc\hosts` because Windows treats `/` as drive-relative. This
breaks 53 tests on Test-windows-latest CI runner.

Bash semantics use forward slashes universally regardless of host OS,
so the resolver now string-only normalizes paths:

- NormalizeToForwardSlashes: \\ → / (preserves UNC as //server/share)
- NormalizePath: split on /, collapse . and .., dedupe slashes,
  preserve leading / (or //, or X: drive letter), join with /
- TryResolveAbsolutePath uses these helpers instead of Path.GetFullPath
- JoinPath uses string concat with explicit / instead of Path.Combine

Linux: still 296/296 green. Windows runner should now pass — the
`Expected /work/input vs Actual D:\work\input` failures all disappear
because the resolver no longer touches the host's PathSeparator.
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