Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
78da5df
feat(s2-step11): the OwnSharp.WeakTargetProbe (bind + probe modes)
PhysShell Jul 17, 2026
71a7d44
feat(s2-step11): fix_target.py orchestration + verify-target CLI
PhysShell Jul 17, 2026
e2469f4
test(s2-step11): red — verify-target Tier A + full-CLI Tier B acceptance
PhysShell Jul 17, 2026
36cea9a
feat(s2-step11): green — TARGET_BINDING shape check in bind (WRAPPER_…
PhysShell Jul 17, 2026
a44564f
test(s2-step11): red — H1 a candidate wrapper must never bind; ambigu…
PhysShell Jul 17, 2026
fb4fcd1
feat(s2-step11): green — bind never promotes CandidateSymbols to the …
PhysShell Jul 17, 2026
619d3c4
test(s2-step11): red — H2 the wrapper load context must be closed
PhysShell Jul 17, 2026
90ddc9f
feat(s2-step11): green — close the wrapper AssemblyLoadContext (H2)
PhysShell Jul 17, 2026
4961460
test(s2-step11): red — H3 execution-root isolation + full revalidation
PhysShell Jul 17, 2026
8c692b8
feat(s2-step11): green — literal G5 execution-root isolation + revali…
PhysShell Jul 17, 2026
97db6e3
test(s2-step11): red — H4 bounded child + strict result validation + …
PhysShell Jul 17, 2026
9876b36
feat(s2-step11): green — bounded child runner + strict validation + b…
PhysShell Jul 17, 2026
a44368c
test(s2-step11): red — K1 drift categories + K2 closed-schema validation
PhysShell Jul 17, 2026
f0af45c
feat(s2-step11): green — K1 drift categories + K2 closed-schema (fix_…
PhysShell Jul 17, 2026
964507c
test(s2-step11): red — K3 WRAPPER_RUNTIME_UNSUPPORTED needs a positiv…
PhysShell Jul 17, 2026
1045ec8
feat(s2-step11): green — positive runtime-incompat predicate in bind …
PhysShell Jul 17, 2026
5f0984a
test(s2-step11): red — L1 positive runtime-FAMILY incompatibility
PhysShell Jul 17, 2026
4cc5737
feat(s2-step11): green — positive runtime-FAMILY predicate in bind (L1)
PhysShell Jul 17, 2026
e1578a7
test(s2-step11): red — L2 exact consumed-schema + L3 strict failure c…
PhysShell Jul 17, 2026
c7ab5e4
feat(s2-step11): green — exact consumed-schema (L2) + strict failure …
PhysShell Jul 17, 2026
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
11 changes: 10 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,12 @@ jobs:
python-version: "3.13"
- uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4
with:
dotnet-version: "8.0.x"
# 8.0.x runs the pinned net8.0 extractor/probe; 9.0.x is only needed to BUILD the
# deliberately-incompatible net9 wrapper fixture in the step 11 Tier B suite (which
# then proves it is refused WRAPPER_RUNTIME_UNSUPPORTED under the fixed net8 probe).
dotnet-version: |
8.0.x
9.0.x
Comment on lines +210 to +215

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu

fd -a '^global\.json$' . -x sh -c 'echo "=== $1"; cat "$1"' sh {}
rg -n -C3 'rollForward|sdk.version|TargetFramework' \
  -g 'global.json' -g '*.csproj' frontend/roslyn

Repository: PhysShell/Own.NET

Length of output: 4882


🏁 Script executed:

#!/bin/bash
set -eu

# Inspect the relevant workflow section with line numbers.
sed -n '180,250p' .github/workflows/ci.yml | cat -n

# Look for any SDK pinning or dotnet configuration files.
printf '\n=== SDK pins ===\n'
fd -a '^(global\.json|Directory\.Build\.props|Directory\.Build\.targets)$' . -x sh -c 'echo "=== $1"; cat "$1"' sh {}

printf '\n=== dotnet install/build usage ===\n'
rg -n -C2 'setup-dotnet|dotnet-version|dotnet build|dotnet test|dotnet publish|dotnet run' .github/workflows/ci.yml frontend/roslyn -g '*.yml' -g '*.yaml' -g '*.csproj' -g 'global.json' -g 'Directory.Build.props' -g 'Directory.Build.targets'

Repository: PhysShell/Own.NET

Length of output: 21681


🏁 Script executed:

#!/bin/bash
set -eu

# Show the full workflow area around the SDK installation and subsequent build steps.
sed -n '180,320p' .github/workflows/ci.yml | cat -n

# Search for repo-level SDK pinning/configuration files and any build commands.
printf '\n=== SDK/config files ===\n'
fd -a '^(global\.json|Directory\.Build\.props|Directory\.Build\.targets)$' .

printf '\n=== workflow/build references ===\n'
rg -n -C2 'setup-dotnet|dotnet-version|dotnet build|dotnet test|dotnet publish|dotnet run|UseDotNet' .github/workflows/ci.yml frontend/roslyn -g '*.yml' -g '*.yaml' -g '*.csproj' -g 'global.json' -g 'Directory.Build.props' -g 'Directory.Build.targets'

Repository: PhysShell/Own.NET

Length of output: 26917


🏁 Script executed:

#!/bin/bash
set -eu

sed -n '180,320p' .github/workflows/ci.yml | cat -n
printf '\n=== SDK/config files ===\n'
fd -a '^(global\.json|Directory\.Build\.props|Directory\.Build\.targets)$' .
printf '\n=== workflow/build references ===\n'
rg -n -C2 'setup-dotnet|dotnet-version|dotnet build|dotnet test|dotnet publish|dotnet run|UseDotNet' .github/workflows/ci.yml frontend/roslyn -g '*.yml' -g '*.yaml' -g '*.csproj' -g 'global.json' -g 'Directory.Build.props' -g 'Directory.Build.targets'

Repository: PhysShell/Own.NET

Length of output: 26917


🌐 Web query:

GitHub actions/setup-dotnet multiple dotnet-version list SDK selection latest installed global.json dotnet SDK resolver

💡 Result:

When you use the actions/setup-dotnet GitHub Action to install multiple.NET SDK versions, the action installs all specified versions side-by-side on the runner [1][2]. However, the.NET SDK selection—which version is actually used when you run the dotnet command—is governed by the.NET SDK resolver's standard logic, not by the order in which the action installed them [3][4]. Here is how the selection works and how you can manage it: 1. How the.NET SDK Resolver Selects a Version By default, the dotnet CLI automatically selects the latest installed.NET SDK version [2][4]. This behavior is a fundamental part of the.NET design and occurs regardless of which versions were installed by the setup-dotnet action [3]. 2. The Role of global.json The presence of a global.json file in your project or repository is the primary mechanism to override this "latest version" default [4][5]. The.NET CLI iteratively searches for a global.json file by traversing upward from the current working directory [4]. If a file is found, it instructs the resolver to use the specific version defined in that file, subject to your defined roll-forward policy [6][4]. 3. Managing Multiple Versions with setup-dotnet Because the setup-dotnet action installs multiple versions without automatically creating a global.json file, the system default (the latest installed version) will be used by the dotnet CLI unless you explicitly take control [3]. To ensure a specific version from your installed set is used, you have two primary options: - Use a global.json file: Explicitly include a global.json file in your repository [4]. When the dotnet CLI runs, it will detect this file and bind to the required version, provided that version was installed by the action [4]. - Matrix Strategy (Recommended for CI): Instead of installing multiple versions in one step, use a matrix strategy in your GitHub Actions workflow [7][2]. This allows you to run your build/test jobs for each version independently, ensuring that the environment is explicitly configured for the specific version you intend to test [8]. Example of using a matrix strategy: jobs: build: runs-on: ubuntu-latest strategy: matrix: dotnet-version: [ '8.0.x', '9.0.x' ] steps: - uses: actions/checkout@v6 - name: Setup dotnet uses: actions/setup-dotnet@v5 with: dotnet-version: ${{ matrix.dotnet-version }} - run: dotnet build Summary of Behavior The action installs all requested versions [2]. If no global.json is present, the highest version number installed on the runner will be used by the dotnet CLI [2][4]. If you need to use a non-latest version that you installed, you must provide a global.json file to direct the resolver to the specific version [3][4].

Citations:


Pin the net8 build steps to 8.0.x
Installing 9.0.x alongside 8.0.x lets dotnet resolve to the newest SDK on this job, so the later dotnet run steps can use the 9.0 toolchain instead of the intended net8 one. Keep 9.0.x scoped to the net9 fixture build, or pin the net8 steps explicitly.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml around lines 210 - 215, Update the CI workflow’s
.NET setup and subsequent net8 probe/extractor steps so they explicitly use the
8.0.x SDK rather than resolving the newest installed SDK. Keep 9.0.x available
only for the net9 wrapper fixture build, preserving the intended Tier B
incompatibility check.

- name: Extract OwnIR facts from sample C#
run: |
dotnet run --project frontend/roslyn/OwnSharp.Extractor -- \
Expand Down Expand Up @@ -260,6 +265,10 @@ jobs:
env:
OWN_TIERB_REQUIRED: "1"
run: python tests/test_verify_delta_tierb.py
- name: S2 step 11 verified-target-wrapper gate (Tier B, full public CLI)
env:
OWN_TIERB_REQUIRED: "1"
run: python tests/test_verify_target_tierb.py
- name: Check facts through the core
run: |
out=$(python -m ownlang ownir "$RUNNER_TEMP/facts.json" || true)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">

<!-- S2 Step 11: the fixed Verified Target Wrapper probe. Two internal modes: bind (Roslyn
SemanticModel over the pristine preimage plus the accepted Step 8 postimage; per-finding
callsite bijection, G1; framework references from the SELECTED runtime the probe is
pinned to, plus the ordered reference slots, G2) and probe (a fresh child that loads the
derived wrapper from its EXACT materialized slot path via a dedicated AssemblyLoadContext,
G3, runs the runtime-compatibility preflight, G4, then the frozen GC harness for ONE
attempt). No code generation, build, restore, or NuGet happens inside verify-target; this
project is pre-built and passed as the probe-dll input. -->
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AssemblyName>OwnSharp.WeakTargetProbe</AssemblyName>
<Deterministic>true</Deterministic>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2" />
</ItemGroup>

</Project>
760 changes: 760 additions & 0 deletions frontend/roslyn/OwnSharp.WeakTargetProbe/Program.cs

Large diffs are not rendered by default.

58 changes: 55 additions & 3 deletions ownlang/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -672,8 +672,58 @@ def _cmd_verify_delta(rest: list[str]) -> int:
return 0


def _cmd_verify_target(rest: list[str]) -> int:
"""S2 step 11: `own-fix subscriptions verify-target` — the fake-target gate. Binds the
accepted Step 8 bundle + Step 10 delta, runs the fixed OwnSharp.WeakTargetProbe (Roslyn
callsite bijection, then three isolated runtime probes) over the wrapper the postimage
actually calls, and proves it is a genuine non-retaining subscription."""
from ownlang.fix_gate import GateError
from ownlang.fix_target import TargetError, run_verify_target

flags = {"--bundle", "--root", "--plan", "--candidates", "--delta", "--out",
"--probe-dll", "--wrapper-ordinal"}
parsed = _own_fix_parse(rest, flags, {"--ref-dir"})
if parsed is None:
return 2
positional, opts = parsed
for f in flags:
if rest.count(f) > 1:
print(f"own-fix: {f} given more than once", file=sys.stderr)
return 2
required = ("--bundle", "--root", "--plan", "--candidates", "--delta", "--out")
if positional or not all(opts.get(k) for k in required):
print("usage: own-fix subscriptions verify-target --bundle <step8-bundle> "
"--root <pristine-source-root> --plan <validated-plan.json> "
"--candidates <candidates.json> --delta <step10-delta-result.json> "
"--out <target-evidence-dir> [--ref-dir <dir>]... "
"[--probe-dll <probe.dll>] [--wrapper-ordinal <N>]", file=sys.stderr)
return 2
wrapper_ordinal = None
if opts.get("--wrapper-ordinal") is not None:
raw = opts["--wrapper-ordinal"]
if not raw.isdigit():
print("own-fix: --wrapper-ordinal must be a non-negative integer", file=sys.stderr)
return 2
wrapper_ordinal = int(raw)
try:
published = run_verify_target(
opts["--bundle"], opts["--root"], opts["--plan"], opts["--candidates"],
opts["--delta"], opts.get("--probe-dll"), opts["--out"],
opts.get("--ref-dir") or [], wrapper_ordinal)
except (TargetError, GateError) as exc:
print(f"own-fix: refuse: {exc.category}: {exc}", file=sys.stderr)
return 2
except Exception as exc: # fail closed
print(f"own-fix: refuse: INFRASTRUCTURE: internal error "
f"({type(exc).__name__}: {exc})", file=sys.stderr)
return 2
print(f"own-fix: wrote target-result.json -> {published}")
return 0


def cmd_own_fix(rest: list[str]) -> int:
"""`own-fix subscriptions {candidates|render|validate-plan|apply|gate|verify-delta} ...`."""
"""`own-fix subscriptions {candidates|render|validate-plan|apply|gate|verify-delta|
verify-target} ...`."""
Comment on lines 724 to +726

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Add verify-target to the short-form usage message.

The new verb is documented and dispatched here, but the len(rest) < 2 path on Lines 728-729 still lists only through verify-delta, giving users stale CLI guidance.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ownlang/__main__.py` around lines 724 - 726, Update the short-form usage
message in cmd_own_fix for the len(rest) < 2 path to include verify-target
alongside the existing subscription verbs, keeping the documented and dispatched
command list consistent.

if len(rest) < 2 or rest[0] != "subscriptions":
print("usage: python -m ownlang own-fix subscriptions "
"{candidates|render|validate-plan|apply|gate|verify-delta} ...", file=sys.stderr)
Expand All @@ -691,8 +741,10 @@ def cmd_own_fix(rest: list[str]) -> int:
return _cmd_gate(args)
if verb == "verify-delta":
return _cmd_verify_delta(args)
print(f"own-fix: unknown subcommand {verb!r} "
"(candidates | render | validate-plan | apply | gate | verify-delta)", file=sys.stderr)
if verb == "verify-target":
return _cmd_verify_target(args)
print(f"own-fix: unknown subcommand {verb!r} (candidates | render | validate-plan | apply "
"| gate | verify-delta | verify-target)", file=sys.stderr)
return 2


Expand Down
Loading
Loading