From 13a70c2375c56eb8ed6b0d86636e405b066028ca Mon Sep 17 00:00:00 2001 From: dh Date: Fri, 24 Jul 2026 19:00:45 +0200 Subject: [PATCH] feat: detect host operating system at startup and provide platform-specific guidance --- MeetingAssistant.Tests/HealthEndpointTests.cs | 13 +++++ .../WorkflowRulesEditorTests.cs | 55 +++++++++++++++++++ MeetingAssistant/HostOperatingSystem.cs | 26 +++++++++ MeetingAssistant/Program.cs | 1 + .../WorkflowRulesEditorInstructionBuilder.cs | 30 +++++++++- README.md | 2 + docs/meeting-assistant-configuration.md | 3 +- docs/meeting-workflow-engine.md | 2 + global.json | 6 ++ .../detect-host-operating-system/design.md | 55 +++++++++++++++++++ .../implementation-evidence.md | 42 ++++++++++++++ .../detect-host-operating-system/proposal.md | 28 ++++++++++ .../specs/meeting-session/spec.md | 40 ++++++++++++++ .../detect-host-operating-system/tasks.md | 11 ++++ 14 files changed, 312 insertions(+), 2 deletions(-) create mode 100644 MeetingAssistant/HostOperatingSystem.cs create mode 100644 global.json create mode 100644 openspec/changes/detect-host-operating-system/design.md create mode 100644 openspec/changes/detect-host-operating-system/implementation-evidence.md create mode 100644 openspec/changes/detect-host-operating-system/proposal.md create mode 100644 openspec/changes/detect-host-operating-system/specs/meeting-session/spec.md create mode 100644 openspec/changes/detect-host-operating-system/tasks.md diff --git a/MeetingAssistant.Tests/HealthEndpointTests.cs b/MeetingAssistant.Tests/HealthEndpointTests.cs index 615ec4e..2ae66de 100644 --- a/MeetingAssistant.Tests/HealthEndpointTests.cs +++ b/MeetingAssistant.Tests/HealthEndpointTests.cs @@ -41,6 +41,19 @@ public sealed class HealthEndpointTests : IClassFixture(); + var second = factory.Services.GetRequiredService(); + + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Same(first, second); + Assert.Equal(HostOperatingSystem.DetectCurrent(), first); + } + [Fact] public async Task ApplicationStartupDeletesStaleTemporaryRecordings() { diff --git a/MeetingAssistant.Tests/WorkflowRulesEditorTests.cs b/MeetingAssistant.Tests/WorkflowRulesEditorTests.cs index 109a9ce..170bf22 100644 --- a/MeetingAssistant.Tests/WorkflowRulesEditorTests.cs +++ b/MeetingAssistant.Tests/WorkflowRulesEditorTests.cs @@ -732,6 +732,7 @@ public sealed class WorkflowRulesEditorTests var root = Path.Combine(Path.GetTempPath(), "meeting-assistant-tests", Guid.NewGuid().ToString("N")); var rulesPath = Path.Combine(root, "rules.yaml"); var builder = new WorkflowRulesEditorInstructionBuilder( + HostOperatingSystem.DetectCurrent(), NullLogger.Instance); var instructions = await builder.BuildAsync(new MeetingAssistantOptions @@ -749,10 +750,61 @@ public sealed class WorkflowRulesEditorTests Assert.Contains("list_recent_summaries", instructions); } + [Fact] + public async Task InstructionBuilderUsesWindowsCommandsAndConceptsOnWindows() + { + var builder = new WorkflowRulesEditorInstructionBuilder( + new HostOperatingSystem(HostOperatingSystemKind.Windows), + NullLogger.Instance); + + var instructions = await builder.BuildAsync(new MeetingAssistantOptions(), CancellationToken.None); + + Assert.Contains("Detected host operating system: Windows", instructions); + Assert.Contains("PowerShell", instructions); + Assert.Contains("Windows-style paths", instructions); + Assert.Contains("Windows services", instructions); + Assert.Contains("Task Manager", instructions); + Assert.Contains("Do not use macOS-only commands or concepts", instructions); + Assert.Contains("does not make unavailable integrations available", instructions); + } + + [Fact] + public async Task InstructionBuilderUsesMacOSCommandsAndConceptsOnMacOS() + { + var builder = new WorkflowRulesEditorInstructionBuilder( + new HostOperatingSystem(HostOperatingSystemKind.MacOS), + NullLogger.Instance); + + var instructions = await builder.BuildAsync(new MeetingAssistantOptions(), CancellationToken.None); + + Assert.Contains("Detected host operating system: macOS", instructions); + Assert.Contains("zsh", instructions); + Assert.Contains("POSIX-style paths", instructions); + Assert.Contains("launchd and LaunchAgents", instructions); + Assert.Contains("Activity Monitor", instructions); + Assert.Contains("Do not use Windows-only commands or concepts", instructions); + Assert.Contains("does not make unavailable integrations available", instructions); + } + + [Fact] + public async Task InstructionBuilderUsesPortableConceptsOnUnsupportedHosts() + { + var builder = new WorkflowRulesEditorInstructionBuilder( + new HostOperatingSystem(HostOperatingSystemKind.Unsupported), + NullLogger.Instance); + + var instructions = await builder.BuildAsync(new MeetingAssistantOptions(), CancellationToken.None); + + Assert.Contains("Detected host operating system: unsupported", instructions); + Assert.Contains("portable .NET concepts", instructions); + Assert.Contains("Do not assume Windows or macOS", instructions); + } + [Fact] public async Task InstructionBuilderIncludesProjectSyncGuidanceForCorrectedMeetingNotes() { var builder = new WorkflowRulesEditorInstructionBuilder( + HostOperatingSystem.DetectCurrent(), NullLogger.Instance); var instructions = await builder.BuildAsync(new MeetingAssistantOptions(), CancellationToken.None); @@ -767,6 +819,7 @@ public sealed class WorkflowRulesEditorTests public async Task InstructionBuilderTreatsAssistantContextAsMeetingMemoryDuringRepairs() { var builder = new WorkflowRulesEditorInstructionBuilder( + new HostOperatingSystem(HostOperatingSystemKind.MacOS), NullLogger.Instance); var options = new MeetingAssistantOptions { @@ -784,6 +837,8 @@ public sealed class WorkflowRulesEditorTests Assert.Contains("read the matching assistant context", instructions); Assert.Contains("problems, missing information, assumptions, prior fixes, and conclusions", instructions); Assert.Contains("append a concise record of your fixes and conclusions", instructions); + Assert.Contains("Detected host operating system: macOS", instructions); + Assert.Contains("zsh", instructions); } [Fact] diff --git a/MeetingAssistant/HostOperatingSystem.cs b/MeetingAssistant/HostOperatingSystem.cs new file mode 100644 index 0000000..41f4920 --- /dev/null +++ b/MeetingAssistant/HostOperatingSystem.cs @@ -0,0 +1,26 @@ +namespace MeetingAssistant; + +public enum HostOperatingSystemKind +{ + Windows, + MacOS, + Unsupported +} + +public sealed record HostOperatingSystem(HostOperatingSystemKind Kind) +{ + public static HostOperatingSystem DetectCurrent() + { + if (OperatingSystem.IsWindows()) + { + return new HostOperatingSystem(HostOperatingSystemKind.Windows); + } + + if (OperatingSystem.IsMacOS()) + { + return new HostOperatingSystem(HostOperatingSystemKind.MacOS); + } + + return new HostOperatingSystem(HostOperatingSystemKind.Unsupported); + } +} diff --git a/MeetingAssistant/Program.cs b/MeetingAssistant/Program.cs index 9b1e6e1..02f66a5 100644 --- a/MeetingAssistant/Program.cs +++ b/MeetingAssistant/Program.cs @@ -17,6 +17,7 @@ using Microsoft.Extensions.Options; var builder = WebApplication.CreateBuilder(args); builder.Logging.AddProvider(new MeetingAssistantFileLoggerProvider()); builder.Services.Configure(builder.Configuration.GetSection("MeetingAssistant")); +builder.Services.AddSingleton(HostOperatingSystem.DetectCurrent()); builder.Services.AddSingleton(); #if WINDOWS builder.Services.AddSingleton(); diff --git a/MeetingAssistant/Workflow/WorkflowRulesEditorInstructionBuilder.cs b/MeetingAssistant/Workflow/WorkflowRulesEditorInstructionBuilder.cs index 7921c83..fa10e37 100644 --- a/MeetingAssistant/Workflow/WorkflowRulesEditorInstructionBuilder.cs +++ b/MeetingAssistant/Workflow/WorkflowRulesEditorInstructionBuilder.cs @@ -38,10 +38,14 @@ public sealed class WorkflowRulesEditorInstructionBuilder : IWorkflowRulesEditor Explain the final change briefly after the tools finish. """; + private readonly HostOperatingSystem hostOperatingSystem; private readonly ILogger logger; - public WorkflowRulesEditorInstructionBuilder(ILogger logger) + public WorkflowRulesEditorInstructionBuilder( + HostOperatingSystem hostOperatingSystem, + ILogger logger) { + this.hostOperatingSystem = hostOperatingSystem; this.logger = logger; } @@ -53,8 +57,10 @@ public sealed class WorkflowRulesEditorInstructionBuilder : IWorkflowRulesEditor : editorOptions.InitialPrompt!; var rulesPath = WorkflowRulesPathResolver.Resolve(options.Automation.RulesPath) ?? ""; var docs = await ReadWorkflowDocsAsync(cancellationToken); + var platformGuidance = BuildPlatformGuidance(hostOperatingSystem); return configuredPrompt.Trim() + Environment.NewLine + Environment.NewLine + + platformGuidance + Environment.NewLine + Environment.NewLine + $"Configured workflow rules file: {rulesPath}" + Environment.NewLine + Environment.NewLine + "Configuration tools can read and replace the local appsettings JSON file. Use read_config_docs for the configuration reference." + Environment.NewLine + Environment.NewLine + "Log tools can read and search the current application-owned log file and four rotated older files under the temp log folder." + Environment.NewLine + Environment.NewLine + @@ -69,6 +75,28 @@ public sealed class WorkflowRulesEditorInstructionBuilder : IWorkflowRulesEditor "```"; } + private static string BuildPlatformGuidance(HostOperatingSystem operatingSystem) + { + var platformGuidance = operatingSystem.Kind switch + { + HostOperatingSystemKind.Windows => """ + Detected host operating system: Windows. + Use Windows-native operational guidance: PowerShell and native Windows commands, Windows-style paths, Windows environment-variable conventions, Windows services and processes, and Task Manager. Do not use macOS-only commands or concepts. + """, + HostOperatingSystemKind.MacOS => """ + Detected host operating system: macOS. + Use macOS-native operational guidance: zsh and native macOS commands, POSIX-style paths, macOS environment-variable conventions, launchd and LaunchAgents, application processes, and Activity Monitor. Do not use Windows-only commands or concepts. + """, + _ => """ + Detected host operating system: unsupported. + Use portable .NET concepts. Do not assume Windows or macOS commands, paths, services, environment conventions, or desktop features. + """ + }; + + return platformGuidance + Environment.NewLine + + "Prefer the provided Meeting Assistant tools over shell commands when a matching tool exists. Operating-system detection selects appropriate guidance; it does not make unavailable integrations available."; + } + private async Task ReadWorkflowDocsAsync(CancellationToken cancellationToken) { foreach (var path in RuntimeContentLocator.CandidateDocumentationPaths("meeting-workflow-engine.md")) diff --git a/README.md b/README.md index 4c68aaa..600a101 100644 --- a/README.md +++ b/README.md @@ -144,6 +144,8 @@ Meeting-specific automation lives in a local YAML file, not in committed persona The tray menu exposes `Open agent`, which opens the `Meeting Summary Agent` window. It can edit workflow rules with validation, inspect logs and health/status, manage speaker identities and samples, run ASR diagnostics, and read/write scoped meeting/project artifacts through explicit tools. +At startup, Meeting Assistant detects whether the host is Windows or macOS and includes that immutable runtime context in the interactive settings/logs assistant instructions. On Windows the assistant uses Windows commands and concepts such as PowerShell, Windows paths, services, and Task Manager. On macOS it uses zsh, POSIX paths, launchd/LaunchAgents, and Activity Monitor. This guidance is also appended when a custom interactive-agent prompt is configured. macOS audio capture is available in the portable build; Windows-only tray, hotkey, Outlook, notification, and screenshot features remain unavailable there. + Detailed workflow syntax and extension guidance live in `docs/meeting-workflow-engine.md`. ## Development And CI diff --git a/docs/meeting-assistant-configuration.md b/docs/meeting-assistant-configuration.md index 605629e..a4d0048 100644 --- a/docs/meeting-assistant-configuration.md +++ b/docs/meeting-assistant-configuration.md @@ -382,7 +382,8 @@ The top-level `Logging` section is standard ASP.NET Core logging configuration a Independently from stdout and stderr redirection, Meeting Assistant writes an application-owned log under: ```text -%TEMP%\MeetingAssistant\Logs\meeting-assistant.log +Windows: %TEMP%\MeetingAssistant\Logs\meeting-assistant.log +macOS: $TMPDIR/MeetingAssistant/Logs/meeting-assistant.log ``` On startup it rotates the previous current file to `meeting-assistant.log.1` and keeps up to `.4`. The tray-launched assistant reads and searches these current and rotated files. If another app instance or test host still has the file open, rotation is skipped and logging appends to the current file so startup is not blocked. diff --git a/docs/meeting-workflow-engine.md b/docs/meeting-workflow-engine.md index 8287fd9..9f6fc40 100644 --- a/docs/meeting-workflow-engine.md +++ b/docs/meeting-workflow-engine.md @@ -24,6 +24,8 @@ If the configured path is empty, missing, or points to a blank file, the workflo The tray menu includes `Open agent`, which opens the `Meeting Summary Agent` chat window for this configured rules file, the local speaker identity database, appsettings configuration, and application logs. The assistant uses the summarizer agent configuration by default and can be overridden through `MeetingAssistant:WorkflowRulesEditor`. +Meeting Assistant detects the host operating system once during application startup and appends that context to the interactive agent prompt. Windows hosts receive PowerShell, Windows-path, Windows-service, and Task Manager guidance. macOS hosts receive zsh, POSIX-path, launchd/LaunchAgent, and Activity Monitor guidance. Other hosts receive neutral portable guidance. The platform context remains present when `WorkflowRulesEditor:InitialPrompt` is configured, and it does not imply that unavailable platform integrations have been implemented. + ```json { "MeetingAssistant": { diff --git a/global.json b/global.json new file mode 100644 index 0000000..512142d --- /dev/null +++ b/global.json @@ -0,0 +1,6 @@ +{ + "sdk": { + "version": "10.0.100", + "rollForward": "latestFeature" + } +} diff --git a/openspec/changes/detect-host-operating-system/design.md b/openspec/changes/detect-host-operating-system/design.md new file mode 100644 index 0000000..4eacee6 --- /dev/null +++ b/openspec/changes/detect-host-operating-system/design.md @@ -0,0 +1,55 @@ +## Context + +Meeting Assistant already separates many Windows-only implementations at compile time, while its portable service surface can run on macOS. The interactive settings/logs assistant is different: its model instructions are currently platform-neutral and do not tell the model which local operating system it is helping to operate. As a result, responses can mix PowerShell, Windows path and service concepts with macOS shells, POSIX paths, and launchd concepts. + +The host platform is stable for the lifetime of one application process, so it should be detected once during startup and passed to consumers as runtime context. + +## Goals / Non-Goals + +**Goals:** + +- Detect Windows and macOS explicitly when the process starts. +- Give the interactive settings/logs assistant unambiguous host-platform context. +- Require Windows-native operational guidance on Windows and macOS-native guidance on macOS. +- Prevent the assistant from presenting unavailable platform features as if they existed. +- Retain safe, neutral behavior on other hosts used for build or test execution. + +**Non-Goals:** + +- Implement macOS audio capture, global hotkeys, tray UI, Outlook integration, active-window screenshots, or notifications. +- Change automatic meeting-summary instructions, which do not operate the local application environment. +- Add a user-configurable OS override. +- Translate every internal process invocation into a shell script; existing argument-based process execution remains portable where it already is. + +## Decisions + +### Detect once and inject immutable runtime context + +Startup will create one immutable host-operating-system value using .NET runtime checks and register it as a singleton. The interactive instruction builder will consume that value instead of invoking static OS checks itself. + +This makes startup responsible for environment detection, keeps model instruction generation deterministic, and lets behavior tests supply explicit Windows and macOS values without depending on the test runner's host. + +Alternative considered: call `OperatingSystem.IsWindows()` or `OperatingSystem.IsMacOS()` directly inside the instruction builder. That would couple instruction tests to their host and repeat environment detection at the usage site. + +### Append platform guidance even when a custom prompt is configured + +The detected platform and platform constraints will be part of the always-appended runtime context, alongside configured paths and tool descriptions. A custom initial prompt may change the assistant persona, but it must not erase the factual host environment. + +Alternative considered: include platform text only in the built-in prompt. That would recreate the current ambiguity whenever `WorkflowRulesEditor:InitialPrompt` is configured. + +### Use explicit platform concepts and exclusions + +Windows guidance will name PowerShell, Windows paths, environment variables, processes, services, and Task Manager concepts while excluding macOS-only instructions. macOS guidance will name zsh/POSIX paths, launchd/LaunchAgents, Activity Monitor, and macOS environment conventions while excluding Windows-only instructions. + +Both branches will remind the assistant that it must respect the application's actual feature availability. Platform detection informs operational language; it does not create platform integrations. + +### Preserve a neutral unsupported-host fallback + +Linux and other hosts may be used for CI or the portable service surface. Those hosts will be identified as unsupported for platform-specific guidance and will receive portable .NET/tool guidance without being mislabeled as Windows or macOS. + +## Risks / Trade-offs + +- [Prompt guidance cannot guarantee every model response uses the correct command syntax] → Make the platform explicit, name positive concepts, and explicitly forbid cross-platform substitutions. +- [Platform examples can become too prescriptive] → Keep the guidance at the command/concept family level and prefer the assistant's built-in tools when available. +- [Users may interpret macOS detection as full macOS feature support] → State in both the prompt and documentation that feature availability remains separate from OS detection. + diff --git a/openspec/changes/detect-host-operating-system/implementation-evidence.md b/openspec/changes/detect-host-operating-system/implementation-evidence.md new file mode 100644 index 0000000..9ebfe6e --- /dev/null +++ b/openspec/changes/detect-host-operating-system/implementation-evidence.md @@ -0,0 +1,42 @@ +## Implementation Evidence + +Date: 2026-07-21 +Host: macOS arm64 + +### Behavior verification + +- Focused interactive-instruction and startup tests: + - Command: `dotnet test MeetingAssistant.Tests/MeetingAssistant.Tests.csproj --filter 'FullyQualifiedName~InstructionBuilder|FullyQualifiedName~ApplicationStartupRegistersDetectedHostOperatingSystemOnce' --no-restore --nologo` + - Result: passed, 11/11. +- The focused tests cover Windows guidance, macOS guidance, unsupported-host fallback, custom-prompt retention, and singleton startup detection. + +### Build and spec verification + +- Portable application build: + - Command: `dotnet build MeetingAssistant/MeetingAssistant.csproj -f net10.0 --no-restore --nologo` + - Result: succeeded with 0 warnings and 0 errors. +- OpenSpec validation: + - Command: `openspec validate detect-host-operating-system --strict` + - Result: valid. +- Diff check: + - Command: `git diff --check` + - Result: passed. + +### Broader test result and known limitations + +- Full portable test project: + - Command: `dotnet test MeetingAssistant.Tests/MeetingAssistant.Tests.csproj --no-restore --nologo` + - Result: 422 passed, 9 failed. + - The 9 failures are the pre-existing macOS failures identified before this change: Windows/GDI+ image rendering, Windows-path expectations, and Windows user-environment behavior. None exercise the new host detection or platform instruction output. +- Windows target: + - Restore with `EnableWindowsTargeting=true` succeeded. + - Native Windows build cannot complete on macOS because the Windows SDK attempts to execute `MakePri.exe` and returns `Exec format error`. Windows CI or a Windows host remains the appropriate verification environment for that target. + +### Refactoring review + +- DRY review consolidated shared platform-guidance policy text and reused the production detector in the startup test. +- SOLID review found no actionable issue. +- KISS review found no actionable simplification. + +The live Meeting Assistant process was not restarted or modified during verification. + diff --git a/openspec/changes/detect-host-operating-system/proposal.md b/openspec/changes/detect-host-operating-system/proposal.md new file mode 100644 index 0000000..ff928e6 --- /dev/null +++ b/openspec/changes/detect-host-operating-system/proposal.md @@ -0,0 +1,28 @@ +## Why + +The interactive Meeting Assistant settings/logs assistant can run against either a Windows or macOS installation, but its instructions do not currently identify the host operating system. Without that context, the agent can suggest Windows commands, paths, services, or desktop concepts on macOS, or suggest macOS concepts on Windows. + +## What Changes + +- Detect the host operating system when Meeting Assistant starts. +- Make the detected platform available to the interactive settings/logs assistant instruction builder. +- Tell the assistant to use Windows commands and concepts on Windows and macOS commands and concepts on macOS. +- Keep a platform-neutral fallback for unsupported hosts rather than incorrectly claiming Windows or macOS. +- Document that platform-aware agent guidance does not add missing platform integrations such as macOS audio capture or Windows-only desktop features. + +## Capabilities + +### New Capabilities + +None. + +### Modified Capabilities + +- `meeting-session`: Define how the interactive settings/logs assistant receives and applies detected host operating-system context. + +## Impact + +- Application startup dependency registration. +- Interactive settings/logs assistant instructions and behavior tests. +- Runtime documentation describing platform-aware operational guidance. + diff --git a/openspec/changes/detect-host-operating-system/specs/meeting-session/spec.md b/openspec/changes/detect-host-operating-system/specs/meeting-session/spec.md new file mode 100644 index 0000000..278084c --- /dev/null +++ b/openspec/changes/detect-host-operating-system/specs/meeting-session/spec.md @@ -0,0 +1,40 @@ +## ADDED Requirements + +### Requirement: Interactive agent uses detected host operating-system context +Meeting Assistant SHALL detect the host operating system when the application starts and SHALL make that immutable runtime context available to the interactive settings/logs assistant. + +When the detected host is Windows, the interactive assistant instructions SHALL identify Windows as the runtime platform and SHALL direct the assistant to use Windows-specific commands, paths, services, environment conventions, and desktop concepts instead of macOS concepts. + +When the detected host is macOS, the interactive assistant instructions SHALL identify macOS as the runtime platform and SHALL direct the assistant to use macOS-specific commands, POSIX paths, launchd services, environment conventions, and desktop concepts instead of Windows concepts. + +Platform-aware instructions SHALL remain present when the interactive assistant uses a configured custom initial prompt. + +The instructions SHALL distinguish platform-aware operational guidance from feature availability and SHALL NOT imply that detecting macOS provides Windows-only or otherwise unavailable integrations. + +For other detected hosts, Meeting Assistant SHALL identify the platform as unsupported for platform-specific guidance and SHALL direct the assistant to prefer portable tools and concepts rather than assuming Windows or macOS. + +#### Scenario: Windows host receives Windows operational guidance +- **GIVEN** Meeting Assistant detected Windows during startup +- **WHEN** it builds the interactive settings/logs assistant instructions +- **THEN** the instructions identify Windows as the runtime platform +- **AND** direct the assistant to use Windows commands and concepts +- **AND** direct the assistant not to substitute macOS commands or concepts + +#### Scenario: macOS host receives macOS operational guidance +- **GIVEN** Meeting Assistant detected macOS during startup +- **WHEN** it builds the interactive settings/logs assistant instructions +- **THEN** the instructions identify macOS as the runtime platform +- **AND** direct the assistant to use macOS commands and concepts +- **AND** direct the assistant not to substitute Windows commands or concepts + +#### Scenario: Custom prompt retains detected platform context +- **GIVEN** Meeting Assistant detected macOS during startup +- **AND** a custom interactive-assistant initial prompt is configured +- **WHEN** it builds the interactive assistant instructions +- **THEN** the instructions contain both the custom prompt and macOS runtime guidance + +#### Scenario: Unsupported host uses neutral guidance +- **GIVEN** Meeting Assistant runs on a host other than Windows or macOS +- **WHEN** it builds the interactive settings/logs assistant instructions +- **THEN** the instructions do not label the host as Windows or macOS +- **AND** direct the assistant to prefer portable tools and concepts diff --git a/openspec/changes/detect-host-operating-system/tasks.md b/openspec/changes/detect-host-operating-system/tasks.md new file mode 100644 index 0000000..a06456c --- /dev/null +++ b/openspec/changes/detect-host-operating-system/tasks.md @@ -0,0 +1,11 @@ +## 1. Runtime Platform Context + +- [x] 1.1 Add behavior tests for Windows and macOS interactive-assistant instructions. +- [x] 1.2 Detect the host operating system once at startup and register immutable runtime context. +- [x] 1.3 Append platform-specific command, path, service, and desktop concepts to interactive-assistant instructions. +- [x] 1.4 Preserve a platform-neutral fallback for unsupported hosts. + +## 2. Documentation and Validation + +- [x] 2.1 Document platform-aware interactive-assistant guidance and its feature-support boundary. +- [x] 2.2 Run focused behavior tests, the full test suite, strict OpenSpec validation, and the required refactoring review; record the known unrelated macOS failures and Windows-host build limitation in implementation evidence.