Skip to content

Commit 79aff7c

Browse files
feat: add Azure.Monitor.OpenTelemetry.AspNetCore package reference (#176)
* squad: log spec 008 milestone and issues session - Merged 9 decision inbox files to decisions.md - Archived old Amy history entries (kept last 90 days) - Updated Farnsworth history: spec 008 directory structure - Updated Amy history: GitHub milestone #4 and issues #170#175 - Created orchestration log: coordinator session - Created session log: spec 008 GitHub milestone creation Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: add Azure.Monitor.OpenTelemetry.AspNetCore package reference Adds Azure.Monitor.OpenTelemetry.AspNetCore for Spec 008 optional Application Insights telemetry export via OpenTelemetry pipeline. Uses the modern OTel-native package over legacy SDK. Refs #170 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 8d70813 commit 79aff7c

5 files changed

Lines changed: 325 additions & 0 deletions

File tree

.squad/agents/amy/history-archive.md

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,89 @@
1+
- Ran 5 sequential iterations of `dotnet clean` + `dotnet test --configuration Release` to diagnose reported flaky tests.
2+
- **Result: STABLE** — All 5 iterations passed with consistent test counts: 387 passed, 1 skipped, 0 failed (total 388).
3+
- Iteration times: 338.9s, 291.9s, 379.9s, 520.9s, 340s (variable duration due to system load, no correlation with failures).
4+
- No failing tests identified across any iteration. One test (`PoshMcp.Tests.Functional.ReturnType.GeneratedMethod.ShouldHandleGetChildItemCorrectly`) consistently skipped.
5+
- Verdict: No evidence of intermittent failures in test suite.
6+
7+
### 2026-04-14: v0.5.4 tool update (local nupkg install)
8+
9+
- Verified latest nupkg in `./nupkg/`: `poshmcp.0.5.4.nupkg`
10+
- Current global tool version: 0.5.3
11+
- PackageId and ToolCommandName both: `poshmcp` (confirmed in .csproj)
12+
- Update command: `dotnet tool update -g poshmcp --add-source ./nupkg --version 0.5.4`
13+
- Verified: `dotnet tool list -g | Select-String poshmcp``poshmcp 0.5.4 poshmcp`
14+
- Local .nupkg directory is specified with `--add-source ./nupkg` (relative path from working directory)
15+
16+
### 2026-04-14: v0.5.6 patch release and GitHub Packages publish
17+
18+
- Version source remains `PoshMcp.Server/PoshMcp.csproj` `<Version>`; bumped `0.5.5``0.5.6` as patch increment.
19+
- Packaging command: `dotnet pack .\PoshMcp.Server\PoshMcp.csproj -c Release -o .\nupkg`
20+
- Produced artifact: `nupkg/poshmcp.0.5.6.nupkg` (25,843,399 bytes).
21+
- GitHub Packages publish command used existing source alias and gh token: `dotnet nuget push .\nupkg\poshmcp.0.5.6.nupkg --api-key (gh auth token) --source github-poshmcp --skip-duplicate`.
22+
- Publish succeeded to `https://nuget.pkg.github.com/usepowershell`.
23+
- Local update command remains: `dotnet tool update -g poshmcp --version 0.5.6 --add-source .\nupkg --ignore-failed-sources`.
24+
- Verified installs: `dotnet tool list -g` shows `poshmcp 0.5.6`; `poshmcp --version` reports `0.5.6+31fa6372ec4b71d7dd68261ba45266c6c8b93817`.
25+
26+
### 2026-07-18: Issue #131 — OTel stdio suppression and appsettings schema
27+
28+
- Added `isStdioMode = false` parameter to `ConfigureOpenTelemetry(HostApplicationBuilder, bool)` in `Program.cs`.
29+
- Guarded `metricsBuilder.AddConsoleExporter()` behind `if (!isStdioMode)` so no OTel console output occurs in stdio transport mode.
30+
- Updated `ConfigureServerServices` call site (stdio-only path) to pass `isStdioMode: true` to `ConfigureOpenTelemetry`.
31+
- `ConfigureOpenTelemetryForHttp` (HTTP path) is a separate method and remains unchanged — HTTP console exporter unaffected.
32+
- `appsettings.json` already had `Logging.File.Path` added by Bender; added the same `Logging.File.Path: ""` schema key to `appsettings.environment-example.json`, `appsettings.azure.json`, and `appsettings.modules.json`.
33+
- Build: `dotnet build PoshMcp.Server/PoshMcp.csproj` → succeeded, 5 pre-existing warnings, 0 errors.
34+
- Committed and pushed to branch `squad/131-stdio-logging-to-file` (commit `8a10311`).
35+
36+
37+
38+
### 2026-07-18: Issue #133 — docker buildx build missing PATH argument
39+
40+
- **Root cause:** `PoshMcp.Server/Program.cs` line ~692, the `build` CLI command handler constructed `buildArgs` as `"build -f {imageFile} -t {imageTag}"` — missing the required build context PATH argument.
41+
- On modern Docker (buildx-as-default), `docker build` delegates to `docker buildx build` which requires a positional PATH/URL/`-` argument. Without it, Docker fails with `'docker buildx build' requires 1 argument`.
42+
- **Fix:** Changed to `$"build -f {imageFile} -t {imageTag} ."` — appending `.` (current directory) as the build context.
43+
- The CI workflow (`publish-packages.yml`) calls `dotnet run -- build --tag "$IMAGE"` which runs the CLI build handler; the Dockerfile is expected to exist in the working directory (repo root), consistent with using `.` as context.
44+
- **Key files:** `PoshMcp.Server/Program.cs` (handler for `buildCommand`), `.github/workflows/publish-packages.yml` (CI step that triggered the failure).
45+
- Branch: `squad/133-fix-docker-buildx-path`, commit `fadbd4d`, PR #134.
46+
- Build verified: `dotnet build PoshMcp.Server/PoshMcp.csproj -c Release` → 0 errors after fix.
47+
48+
### 2026-07-18: PR #138 follow-up — remove orphaned COPY PoshMcp.sln line
49+
50+
- Farnsworth's nit on PR #138: `COPY PoshMcp.sln ./` in the build stage was dead weight after switching restore/build to target `PoshMcp.Server/PoshMcp.csproj`.
51+
- Removed the line and updated the adjacent comment from "Copy solution and project files first" to "Copy project files first".
52+
- Committed as `fix(#136): remove orphaned COPY PoshMcp.sln line from Dockerfile` with Copilot co-author trailer.
53+
- Pushed to `squad/136-fix-container-image-build`; replied to PR with confirmation comment.
54+
- Key lesson: when switching from solution-level to project-level restore/build in a Dockerfile, audit all COPY lines in the build stage — any files that no longer appear in RUN commands become orphaned layers that add noise without value.
55+
56+
## Learnings
57+
58+
### docker.ps1 -GenerateDockerfile switch
59+
60+
- Added `-GenerateDockerfile` [switch] and `-OutputPath` [string] parameters to `docker.ps1`.
61+
- Works with `build`/`build-base` (reads `./Dockerfile`) and `build-custom` (reads `examples/Dockerfile.$Template`).
62+
- `-OutputPath` has no default in `param()` — computed dynamically: `./Dockerfile.generated` for base, `./Dockerfile.<Template>.generated` for custom. This follows the precomputed-optional-parameter skill pattern.
63+
- Header includes: generated-by comment, equivalent build command, ISO 8601 timestamp, and a reminder `docker build -f <output> -t <tag> .` command.
64+
- Azure template appends an extra env-var note line to the header.
65+
- Existing build paths are fully unchanged — switch is gated, no regressions on `run`, `stop`, `logs`, `clean`.
66+
- Cleaned all pre-existing trailing whitespace from the file while editing (file standard: no trailing whitespace).
67+
- Validated syntax with `[System.Management.Automation.Language.Parser]::ParseFile` — zero errors.
68+
69+
### poshmcp build CLI
70+
71+
- `poshmcp build` is a subcommand of the **poshmcp** dotnet global tool (packaged in `PoshMcp.Server/PoshMcp.csproj` with `<PackAsTool>true</PackAsTool>` and `<ToolCommandName>poshmcp</ToolCommandName>`).
72+
- Accepts `--tag <image:tag>` (single tag only), `--modules`, `--type`, `--docker-file` options.
73+
- Under the hood it calls `DockerRunner.BuildDockerBuildArgs``docker/podman build -f Dockerfile -t <tag> .` with auto-detection of docker vs podman.
74+
- Because `poshmcp build` only supports one `--tag`, building both a versioned tag and `latest` requires: call `poshmcp build --tag $VersionedTag` once, then `docker tag $VersionedTag $latestTag` to alias the result — avoiding a double build.
75+
- The deploy script's `Build-AndPushImage` was updated to use this pattern (replaced the direct `docker build -t … -t … -f Dockerfile .` line).
76+
77+
### poshmcp build --generate-dockerfile
78+
79+
- Added `--generate-dockerfile` (bool/switch) and `--dockerfile-output` (string, default `./Dockerfile.generated`) to `poshmcp build`.
80+
- When `--generate-dockerfile` is set, the CLI reads the source Dockerfile, prepends a comment header (generated-by, equivalent build command, ISO 8601 timestamp), writes the result to the output path, prints a success message with the equivalent `docker build` command, and exits 0 — without invoking docker/podman at all.
81+
- Added `DockerRunner.GenerateDockerfile(sourceDockerfilePath, outputPath, imageTag, modules?, sourceImage?)` to `PoshMcp.Server/Cli/DockerRunner.cs`; added `using System.IO;` to that file.
82+
- Switched the build command handler from the typed-parameter `SetHandler` overload to `InvocationContext`-based pattern to cleanly accommodate the two extra options without hitting overload limits.
83+
- Existing `poshmcp build` behavior (without the flag) is fully unchanged — docker detection and build execution path are identical.
84+
- Build verified: `dotnet build PoshMcp.Server/PoshMcp.csproj --configuration Release -v quiet` → 0 errors.
85+
86+
187
# amy - History Archive (Pre-cleanup)
288

389
# Amy Work History
@@ -88,3 +174,4 @@
88174

89175
### 2026-04-13: Intermittent test failure investigation
90176

177+

.squad/agents/amy/history.md

-7.7 KB
Binary file not shown.

.squad/agents/farnsworth/history.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,3 +203,16 @@ Source: earned patterns from PRs #92–#96 and agent histories.
203203
### 2026-04-23: Added session-recall skill
204204

205205
Created `.squad/skills/session-recall/SKILL.md` — project-level skill documenting the `session-recall` CLI tool for coordinator startup context recovery. Covers the lean 3-command startup sequence, how to pass recovered context into spawn prompts, fallback to the SQL-based `session-recovery` template skill, and anti-patterns. This is the preferred pattern over raw `session_store` SQL queries when the CLI is installed.
206+
207+
### 2026-04-25: Spec 008 — Application Insights Logging directory structure
208+
209+
**Actions taken:**
210+
- Created `specs/008-application-insights-logging/` directory with `spec.md`, `tasks.md`, `checklists/requirements.md`
211+
- Deleted old flat spec file from repository root
212+
- Committed and pushed to main
213+
214+
**Result:** Spec 008 now in speckit format matching specs 001–007 naming and structure convention.
215+
216+
## Learnings
217+
218+
Spec: Application Insights optional logging — proposed Azure.Monitor.OpenTelemetry.AspNetCore integration, config-driven opt-in via appsettings ApplicationInsights section. File: specs/008-application-insights-logging/spec.md

.squad/decisions.md

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,3 +179,227 @@ Steven requested that any image-building step in the deploy pipeline go through
179179
**Operational Outcome:** Build and pack completed successfully and produced `artifacts/nupkg/poshmcp.0.8.3.nupkg`.
180180
**Merged from inbox:** `.squad/decisions/inbox/amy-version-bump-pack-update.md`
181181

182+
183+
184+
# Decision: -GenerateDockerfile switch for docker.ps1
185+
186+
**Date:** 2026-07-28
187+
**By:** Amy (DevOps/Platform/Azure)
188+
**Status:** Applied
189+
190+
## What
191+
192+
Added `-GenerateDockerfile` [switch] and `-OutputPath` [string] parameters to `docker.ps1`.
193+
194+
## Decisions Made
195+
196+
1. **`-OutputPath` has no default in `param()`** — default is computed dynamically inside each command block:
197+
- Base build: `./Dockerfile.generated`
198+
- Custom build: `./Dockerfile.<Template>.generated`
199+
This avoids a static default that would be wrong for the `build-custom` case.
200+
201+
2. **Feature scope**`-GenerateDockerfile` is only meaningful for `build`/`build-base` and `build-custom`. It is silently ignored for `run`, `stop`, `logs`, and `clean` (the switch is simply not tested in those branches). No warning emitted — the existing command still executes normally.
202+
203+
3. **Header format** — Includes `# Generated by PoshMcp docker.ps1`, the equivalent `docker build` command, an ISO 8601 timestamp, and a copy-paste-ready build command referencing the output file. Azure template appends an env-var note.
204+
205+
4. **Source content** — The generated file is header + verbatim source Dockerfile content. No mutations to the Dockerfile itself.
206+
207+
5. **`Set-Content -NoNewline`** — Used to avoid appending a spurious trailing newline that `Set-Content` adds by default. Content from `Get-Content -Raw` already contains the file's original line endings.
208+
209+
## Why
210+
211+
Provides a documented, archivable snapshot of the exact Dockerfile used for any build invocation, useful for audit trails, CI artifact storage, and debugging build regressions without re-running the full build.
212+
213+
## Files Changed
214+
215+
- `docker.ps1` — new parameters, updated help block, build command logic
216+
217+
218+
# Decision: poshmcp build --generate-dockerfile
219+
220+
**Date:** 2026-07-28
221+
**By:** Amy (DevOps/Platform)
222+
**Status:** Applied
223+
224+
## What
225+
226+
Added `--generate-dockerfile` and `--dockerfile-output` options to `poshmcp build`.
227+
228+
## Decision Points
229+
230+
1. **New CLI options:**
231+
- `--generate-dockerfile` (bool/switch): when set, write the Dockerfile to disk and exit; do not invoke docker/podman.
232+
- `--dockerfile-output` (string, optional): destination path; default `./Dockerfile.generated`.
233+
234+
2. **Dockerfile header format:**
235+
- `# Generated by poshmcp build`
236+
- `# Equivalent build command: docker build -f <output-path> -t <image-tag> [--build-arg ...] .`
237+
- `# Generated: <ISO 8601 UTC timestamp>`
238+
- Blank line separator before the actual Dockerfile content.
239+
240+
3. **Implementation split:**
241+
- `DockerRunner.GenerateDockerfile(...)` in `Cli/DockerRunner.cs` owns file I/O and header construction.
242+
- `Program.cs` handler owns option parsing and console output (success message + manual build hint).
243+
244+
4. **Handler pattern change:**
245+
- Switched the `buildCommand.SetHandler` from the typed-parameter overload to `InvocationContext`-based pattern to accommodate 8 options without hitting System.CommandLine overload limits.
246+
247+
5. **No docker/podman detection when `--generate-dockerfile` is set:**
248+
- The flag check and early-return happen *before* `DetectDockerCommand()` is called, so the CLI works even in environments without docker/podman installed.
249+
250+
## Rule Going Forward
251+
252+
When adding more than ~6 options to a `System.CommandLine` command handler, use the `InvocationContext`-based `SetHandler` pattern instead of the typed-parameter overload.
253+
254+
255+
# Decision: appsettings bundling uses COPY injection rather than build-arg
256+
257+
**Author:** Bender
258+
**Date:** 2026-05-01
259+
260+
## Decision
261+
262+
`poshmcp build --appsettings` bundles the supplied file into the image by injecting a
263+
`COPY poshmcp-appsettings.json /app/server/appsettings.json` line into the Dockerfile, not via
264+
`--build-arg`.
265+
266+
## Rationale
267+
268+
Using `COPY` is the correct Docker pattern for bundling files into an image:
269+
- `--build-arg` is for scalar configuration values, not file contents.
270+
- Embedding file content in a build-arg would require encoding, hit size limits, and make the
271+
Dockerfile comment unreadable.
272+
- `COPY` is transparent, auditable, and idiomatic — the resulting Dockerfile is self-documenting.
273+
274+
## Implementation
275+
276+
- **Generate mode:** `GenerateDockerfile()` replaces/injects the `COPY` line in the Dockerfile content.
277+
- **Build mode:** the appsettings file is staged as `poshmcp-appsettings.json` in CWD (the Docker
278+
build context), a temp Dockerfile (`.poshmcp-build.dockerfile`) is generated with the injected
279+
`COPY` line, the build runs, and both temp files are cleaned up in a `finally` block.
280+
281+
282+
### 2026-04-24: Bundle install-modules.ps1 in base image
283+
**Decision:** Copy install-modules.ps1 into the base container image at /app/install-modules.ps1
284+
**Why:** Generated Dockerfiles (poshmcp build --generate-dockerfile) are used in repos that don't have this script locally. Bundling it eliminates the COPY dependency.
285+
286+
287+
# Decision: Embed Dockerfiles in PoshMcp Assembly
288+
289+
**Date:** 2026-07-30
290+
**Author:** Bender (Backend Developer)
291+
**Requested by:** Steven Murawski
292+
293+
## Context
294+
295+
`poshmcp build --generate-dockerfile` reads Dockerfile templates from disk at runtime.
296+
When the CLI is installed as a global dotnet tool via `dotnet tool install`, those files
297+
do not exist on the user's machine — only the packed NuGet `.nupkg` payload is present.
298+
This caused `Error: Dockerfile not found at examples/Dockerfile.user` for tool users.
299+
300+
## Decision
301+
302+
Embed the four Dockerfile templates directly in the `PoshMcp` assembly as `EmbeddedResource`
303+
items in `PoshMcp.Server/PoshMcp.csproj`:
304+
305+
- `Dockerfile` (root) → manifest name `PoshMcp.Dockerfiles.Dockerfile`
306+
- `examples/Dockerfile.user``PoshMcp.Dockerfiles.Dockerfile.user`
307+
- `examples/Dockerfile.azure``PoshMcp.Dockerfiles.Dockerfile.azure`
308+
- `examples/Dockerfile.custom``PoshMcp.Dockerfiles.Dockerfile.custom`
309+
310+
`DockerRunner.ReadEmbeddedDockerfile(name)` reads from the assembly manifest stream.
311+
`DockerRunner.GenerateDockerfile(...)` tries embedded first, falls back to disk so local
312+
dev workflows are unaffected.
313+
314+
`Program.cs` build handler: the `File.Exists(imageFile)` guard is now skipped when
315+
`--generate-dockerfile` is active (the source doesn't need to be on disk).
316+
317+
## Consequences
318+
319+
- `poshmcp build --generate-dockerfile` works correctly after `dotnet tool install`.
320+
- Local development (running from source) continues to work via the disk fallback.
321+
- Dockerfile content stays in sync with the assembly version — no runtime drift.
322+
- Four Dockerfiles add negligible size to the assembly (~4 KB total).
323+
324+
325+
# Decision: `--generate-dockerfile` always defaults to `buildType = "custom"`
326+
327+
**Date:** current session
328+
**Author:** Bender (Backend Dev)
329+
**Requested by:** Steven Murawski
330+
331+
## Context
332+
333+
`poshmcp build --generate-dockerfile` is a user-facing command for generating a starter Dockerfile
334+
that the user can customize and use to build their own container on top of the published PoshMcp
335+
base image (`ghcr.io/usepowershell/poshmcp/poshmcp:latest`).
336+
337+
The previous logic branched the default `buildType` on whether `--generate-dockerfile` was active:
338+
339+
```csharp
340+
var buildType = string.IsNullOrWhiteSpace(type)
341+
? (generateDockerfile ? "base" : "custom")
342+
: type.ToLowerInvariant();
343+
```
344+
345+
This caused `--generate-dockerfile` (with no `--type`) to default to `"base"`, which maps to the
346+
root `Dockerfile` — the file for building PoshMcp itself from source. That is wrong for users.
347+
348+
## Decision
349+
350+
Always default to `"custom"` when `--type` is not supplied:
351+
352+
```csharp
353+
var buildType = string.IsNullOrWhiteSpace(type)
354+
? "custom"
355+
: type.ToLowerInvariant();
356+
```
357+
358+
`"custom"` maps to `examples/Dockerfile.user`, which is the correct user-deployment template.
359+
Users who need the source-build Dockerfile can explicitly pass `--type base`.
360+
361+
## Consequences
362+
363+
- `poshmcp build --generate-dockerfile` now emits `examples/Dockerfile.user` content by default ✅
364+
- `poshmcp build` (no flags) is unchanged — still defaults to `"custom"` / `examples/Dockerfile.user`
365+
- `poshmcp build --type base --generate-dockerfile` still works for maintainers who want the source Dockerfile ✅
366+
367+
368+
# Decision: Default build type for `--generate-dockerfile`
369+
370+
**Date:** 2025-07-17
371+
**Author:** Bender (Backend Developer)
372+
**Status:** Implemented
373+
374+
## Context
375+
376+
The `poshmcp build` command supports two image types: `base` (builds the runtime from local source using `./Dockerfile`) and `custom` (builds a derived image using `examples/Dockerfile.user`). The default when `--type` is omitted was `custom`, which makes sense for actual Docker builds because the primary user workflow is building a custom derived image from the published GHCR base.
377+
378+
However, `--generate-dockerfile` is a different operation — it dumps the resolved Dockerfile to disk so the user can inspect or customize it. When no `--type` is specified alongside `--generate-dockerfile`, there is no obvious "custom" Dockerfile to generate (the user hasn't specified modules or a source image), so defaulting to `base` (the plain `./Dockerfile`) is the correct zero-configuration behavior.
379+
380+
## Decision
381+
382+
When `--generate-dockerfile` is used without an explicit `--type`:
383+
- Default `buildType` to `"base"` → uses `./Dockerfile`
384+
385+
When `--generate-dockerfile` is **not** used (actual Docker build) without an explicit `--type`:
386+
- Default `buildType` to `"custom"` → uses `examples/Dockerfile.user` (existing behavior preserved)
387+
388+
## Consequences
389+
390+
- `poshmcp build --generate-dockerfile` now works out of the box without errors.
391+
- The non-generate-dockerfile default remains `custom`, preserving the primary build workflow.
392+
- Users who want to generate the custom Dockerfile must pass `--type custom` explicitly.
393+
394+
395+
### 2026-04-24: User directive — git fetch/rebase workflow
396+
**By:** Steven Murawski (via Copilot)
397+
**What:** Always use `git fetch origin main` followed by `git rebase origin/main` to sync with remote before pushing. Never use merge pulls (`git pull` without `--rebase`).
398+
**Why:** User preference — avoids stray merge commits that can trigger branch protection rejections.
399+
400+
401+
### 2026-04-25: Application Insights logging spec created
402+
**By:** Farnsworth (via Steven Murawski)
403+
**What:** Spec at specs/application-insights-logging.md. Proposes opt-in App Insights via appsettings using Azure.Monitor.OpenTelemetry.AspNetCore. Targets post-0.8.11.
404+
**Why:** Users running PoshMcp in Azure need logs/traces in App Insights without breaking existing logging.
405+

0 commit comments

Comments
 (0)