# SDT (Stan's Dev Tools)

Cross-platform terminal orchestrator for project workflows, toolchain checks, and prerequisite gating.

## Current State

- Standalone `.NET` TUI app (`net10.0`)
- Workflow-first config model in `devtool.json`
- Strict-by-default legacy migration (`targets`-only configs fail unless compat mode is enabled)
- Python-first diagnostics/build script layer under `scripts/`
- Fail-fast execution with install prompt gating for missing prerequisites
- Debug profiles with attach metadata and diagnostics bundle generation
- Workspace-first project switching with support for external project paths
- Workspace-level defaults layering via `sdt-defaults.json` (ancestor defaults merged, project config wins)
- Project status tracking is maintained in `ROADMAP.md`
- Core run-event stream (`RunEvent`) shared by workflow + debug execution (TUI consumes it; GUI-ready)
- Run events are persisted to JSONL at `.sdt/events/` for external tooling/GUI consumers
- TUI includes `SYSTEM -> View run events` to inspect persisted JSONL event logs
- `SYSTEM -> Run config doctor` can apply common autofixes (missing working dirs, legacy migration)

## Run

```powershell
dotnet run --project DevTool.csproj
```

Run from any subdirectory inside a project; SDT walks up to find `devtool.json`.

If `devtool.json` is missing, SDT now offers to scan the repo and generate a default config.

Explicit bootstrap command:

```powershell
dotnet run --project DevTool.csproj -- init
```

Bootstrap detects common stacks (`dotnet`, `npm/node`, `python`, `cargo/tauri`, `git`, `docker`) and generates:

- default workflows
- toolchain/tooling defaults
- debug profiles + diagnostics defaults

## Config Model

SDT supports both:

- `workflows` (preferred)
- `targets` (legacy; compat mode only)

### Legacy Migration Mode (v1.2)

- Default: strict mode
- Behavior: `targets`-only config fails early with migration instructions
- Preview file: SDT writes `devtool.generated.workflows.json` for migration help
- Temporary rollback: set `SDT_LEGACY_MODE=compat`

Permanent fix (recommended):

1. Open `devtool.generated.workflows.json`
2. Copy its `workflows` into `devtool.json`
3. Remove or empty legacy `targets`
4. Run `sdt.exe` again in strict mode

### Workflow shape (preferred)

```json
{
  "id": "build",
  "label": "Build",
  "description": "Build project",
  "group": "Build",
  "dependsOn": [],
  "steps": [
    {
      "id": "dotnet-build",
      "label": "dotnet build",
      "action": "dotnet-build",
      "actionArgs": [],
      "workingDir": ".",
      "requires": [
        { "tool": "dotnet", "installPolicy": "Prompt" }
      ]
    }
  ]
}
```

### Extra sections

- `tooling.tools[].preferredInstallCommands`: preferred install commands per tool
- `tooling.tools[].executables`: explicit executable candidates for non-standard PATH setups
- `project.rootHints`: files/folders that identify project root
- `env`: session-level environment variable editor values
- `debug.profiles[]`: run/attach debug profiles
- `debug.diagnostics`: diagnostics bundle policy (`.sdt/debug` by default)
  - secure default: allowlist-only environment capture
  - set `includeAllEnv=true` to opt into full environment capture

### Workspace Defaults Layering

If SDT finds `sdt-defaults.json` in the project directory tree (current project root or an ancestor), it merges it into the effective config before runtime:

- base layer: `sdt-defaults.json`
- override layer: project `devtool.json` (project values win)

Merge behavior:

- objects merge recursively
- arrays/scalars are replaced when project provides the property

This is useful for shared defaults like toolchains, diagnostics policies, and baseline env definitions across multiple projects in one workspace.

## Execution Behavior

For each workflow step:

1. Resolve dependencies (topological order)
2. Probe required tools
3. If missing, show install commands and prompt (`Prompt` policy)
4. On decline/install failure/step failure, stop immediately
5. Render step summary table with exit code + elapsed time
6. On workflow/debug failure, generate diagnostics bundle when enabled

Installer command precedence:

1. `tooling.tools[].preferredInstallCommands`
2. `scripts/diag.py install-plan`
3. built-in C# fallback templates (used automatically if script planning fails)

When a tool probe fails, SDT now prints probe diagnostics (including command resolution source/path) in run output before prompting for installs.

## Scripts

See [scripts/README.md](/e:/stansshit/csharp/DevTool-master/scripts/README.md).

Primary Python entrypoints:

- `scripts/diag.py`
- `scripts/build.py`
- `scripts/dotnet-min.py`
- `scripts/pip-min.py`
- `scripts/publish-*.py`

## Workspace Support

- Uses `sdt-workspace.json` when present
- If missing, can auto-discover nearby projects containing `devtool.json`
- Workspace screen can add external project roots (absolute paths supported)
- `projects[].disabled`, `projects[].tags`, and `projects[].toolFamilies` are supported

## Dev Shell Bootstrap

Python-first cross-shell dev environment bootstrap:

```powershell
# PowerShell
. ./scripts/dev-shell.ps1

# cmd
scripts\dev-shell.cmd
```

```bash
# bash/zsh
source ./scripts/dev-shell.sh
```

Underlying implementation is `scripts/dev_shell.py`:

- `python scripts/dev_shell.py export --shell pwsh --json`
- `python scripts/dev_shell.py doctor`

## Legacy PowerShell Compatibility

Legacy `.ps1` scripts remain for migration compatibility only. New functionality is implemented in Python scripts first. `script-common.ps1` is legacy-only.

Legacy runtime behavior in v1.2:

- strict mode rejects `targets`-only configs by default
- compat mode (`SDT_LEGACY_MODE=compat`) temporarily allows legacy execution
- TUI `SYSTEM` includes `Migrate legacy targets -> workflows` to apply migration in place (with backup)

Deprecation target:

- v1.x: compatibility only (no new behavior guarantees)
- v2.0: remove legacy `.ps1` scripts from default SDT workflows and docs

## Testing

Run unit/integration tests:

```powershell
dotnet test tests/DevTool.Tests/DevTool.Tests.csproj
```

Run Python script smoke checks:

```powershell
python -m py_compile scripts/*.py
```
