From ab6777a8e1ec21bb3f40d463600ecd06a00eef78 Mon Sep 17 00:00:00 2001 From: Kristopher Turner Date: Sat, 11 Jul 2026 03:19:27 -0400 Subject: [PATCH 1/2] feat(claude): add Claude Code scaffold AB#4942 --- .ai/mcp/mcp-servers.md | 17 ++ .ai/memory/COMMANDS.md | 9 ++ .ai/memory/DECISIONS.md | 5 + .ai/memory/GOTCHAS.md | 5 + .ai/memory/PROJECT_CONTEXT.md | 5 + .ai/state/CURRENT_TASK.md | 12 ++ .ai/state/HANDOFF.md | 16 ++ .ai/state/OPEN_QUESTIONS.md | 5 + .../agents/azurelocal-platform-engineer.md | 33 ++++ .claude/hooks/block-secrets.ps1 | 33 ++++ .claude/hooks/check-context.ps1 | 98 +++++++++++ .claude/hooks/format-on-write.ps1 | 47 ++++++ .claude/hooks/log-tokens.ps1 | 21 +++ .claude/hooks/summarize-session.ps1 | 16 ++ .claude/hooks/validate-path.ps1 | 31 ++++ .claude/settings.json | 145 ++++++----------- .codex/config.toml | 12 ++ .github/copilot-instructions.md | 6 + .gitignore | 2 + .mcp.json | 8 + AGENTS.md | 80 +++++++++ CLAUDE.md | 153 ++---------------- 22 files changed, 527 insertions(+), 232 deletions(-) create mode 100644 .ai/mcp/mcp-servers.md create mode 100644 .ai/memory/COMMANDS.md create mode 100644 .ai/memory/DECISIONS.md create mode 100644 .ai/memory/GOTCHAS.md create mode 100644 .ai/memory/PROJECT_CONTEXT.md create mode 100644 .ai/state/CURRENT_TASK.md create mode 100644 .ai/state/HANDOFF.md create mode 100644 .ai/state/OPEN_QUESTIONS.md create mode 100644 .claude/agents/azurelocal-platform-engineer.md create mode 100644 .claude/hooks/block-secrets.ps1 create mode 100644 .claude/hooks/check-context.ps1 create mode 100644 .claude/hooks/format-on-write.ps1 create mode 100644 .claude/hooks/log-tokens.ps1 create mode 100644 .claude/hooks/summarize-session.ps1 create mode 100644 .claude/hooks/validate-path.ps1 create mode 100644 .codex/config.toml create mode 100644 .github/copilot-instructions.md create mode 100644 .mcp.json create mode 100644 AGENTS.md diff --git a/.ai/mcp/mcp-servers.md b/.ai/mcp/mcp-servers.md new file mode 100644 index 0000000..4aa723d --- /dev/null +++ b/.ai/mcp/mcp-servers.md @@ -0,0 +1,17 @@ +# MCP servers + + + +## HCS Governance MCP + +- **Purpose:** source of truth for standards, hard rules, scope resolution, orchestration guidance, and the auth broker. +- **Endpoint:** `https://mcp.hybridsolutions.cloud/mcp` +- **Transport:** Streamable HTTP (remote) +- **Auth:** OAuth 2.1 brokered to Microsoft Entra; members of `sg-hcs-mcp-users` only. Clients prompt for Entra sign-in on first connect. +- **Bootstrap:** call `bootstrap(repo="azurelocal-platform", client="")` at session start. +- **Per-tool config:** `.mcp.json` (Claude Code), `.codex/config.toml` (Codex), `.gemini/settings.json` (Gemini), `.cursor/mcp.json` (Cursor), `.vscode/mcp.json` (VS Code Copilot). + + diff --git a/.ai/memory/COMMANDS.md b/.ai/memory/COMMANDS.md new file mode 100644 index 0000000..6e5f9cb --- /dev/null +++ b/.ai/memory/COMMANDS.md @@ -0,0 +1,9 @@ +# Commands + + + +```powershell +# TODO: fill in +# TODO: fill in +# TODO: fill in +``` diff --git a/.ai/memory/DECISIONS.md b/.ai/memory/DECISIONS.md new file mode 100644 index 0000000..ab68b41 --- /dev/null +++ b/.ai/memory/DECISIONS.md @@ -0,0 +1,5 @@ +# Decisions + + + +_None recorded yet._ \ No newline at end of file diff --git a/.ai/memory/GOTCHAS.md b/.ai/memory/GOTCHAS.md new file mode 100644 index 0000000..9ecdf08 --- /dev/null +++ b/.ai/memory/GOTCHAS.md @@ -0,0 +1,5 @@ +# Gotchas + + + +_None recorded yet._ diff --git a/.ai/memory/PROJECT_CONTEXT.md b/.ai/memory/PROJECT_CONTEXT.md new file mode 100644 index 0000000..38a9e07 --- /dev/null +++ b/.ai/memory/PROJECT_CONTEXT.md @@ -0,0 +1,5 @@ +# Project context + + + +_Not yet filled in. See CLAUDE.md / AGENTS.md for the auto-generated repo description in the meantime._ diff --git a/.ai/state/CURRENT_TASK.md b/.ai/state/CURRENT_TASK.md new file mode 100644 index 0000000..225315e --- /dev/null +++ b/.ai/state/CURRENT_TASK.md @@ -0,0 +1,12 @@ +# Current task + + + +_Nothing yet - this repo was just onboarded onto the multi-model standard._ + + + diff --git a/.ai/state/HANDOFF.md b/.ai/state/HANDOFF.md new file mode 100644 index 0000000..ac9a9eb --- /dev/null +++ b/.ai/state/HANDOFF.md @@ -0,0 +1,16 @@ +# Handoff + + + +## Last session + +- **What changed and why:** Initial multi-model scaffold onboarding (AGENTS.md, CLAUDE.md shim, Codex/Copilot config, .mcp.json, .ai/ workspace). +- **Files touched:** AGENTS.md, CLAUDE.md, .codex/config.toml, .github/copilot-instructions.md, .mcp.json, .ai/* +- **Commands / tests run and results:** N/A - scaffold only +- **Branch:** main — committed: yes — pushed: no +- **Blockers:** None +- **Exact next steps:** Fill in .ai/memory/PROJECT_CONTEXT.md and .ai/memory/COMMANDS.md with real repo-specific detail. diff --git a/.ai/state/OPEN_QUESTIONS.md b/.ai/state/OPEN_QUESTIONS.md new file mode 100644 index 0000000..08eb792 --- /dev/null +++ b/.ai/state/OPEN_QUESTIONS.md @@ -0,0 +1,5 @@ +# Open questions + + + +_None yet._ diff --git a/.claude/agents/azurelocal-platform-engineer.md b/.claude/agents/azurelocal-platform-engineer.md new file mode 100644 index 0000000..5869807 --- /dev/null +++ b/.claude/agents/azurelocal-platform-engineer.md @@ -0,0 +1,33 @@ +--- +name: azurelocal-platform-engineer +description: azurelocal-platform engineer — general development and maintenance +model: sonnet +tools: + - Read + - Write + - Edit + - Glob + - Grep + - Bash +--- + +You are the Engineer for azurelocal-platform — Repo in the HCS estate managed under the platform engineering standard. + +## Repo structure + +- See CLAUDE.md in this repo for the current directory layout. + +## Stack / conventions + +- Primary language: Mixed +- Commit format: `type(scope): short description` +- No credentials, tokens, or subscription IDs committed to any file. +- Local path: D:/git/azurelocal/platform + +## What you do + +You write and maintain code in this repo according to the type and conventions above. You run linters and validators appropriate to the stack. You create and update files, commit changes, and follow HCS platform standards. + +## Hard rules + +- No credentials, tokens, subscription IDs, or vault passwords committed to any file diff --git a/.claude/hooks/block-secrets.ps1 b/.claude/hooks/block-secrets.ps1 new file mode 100644 index 0000000..a2b9296 --- /dev/null +++ b/.claude/hooks/block-secrets.ps1 @@ -0,0 +1,33 @@ +# PreToolUse hook — blocks writes containing secret patterns +# Event: PreToolUse Write|Edit +# Input: JSON from stdin { tool_name, tool_input: { file_path, content|new_string } } + +$input_json = $input | Out-String +try { $payload = $input_json | ConvertFrom-Json } catch { exit 0 } + +$content = if ($payload.tool_input.content) { $payload.tool_input.content } + elseif ($payload.tool_input.new_string) { $payload.tool_input.new_string } + else { exit 0 } + +$patterns = @( + 'api[_-]?key\s*[:=]\s*[''"]?[A-Za-z0-9+/]{20,}', + 'password\s*[:=]\s*[''"]?[^\s''";]{8,}', + 'secret\s*[:=]\s*[''"]?[A-Za-z0-9+/]{16,}', + 'token\s*[:=]\s*[''"]?[A-Za-z0-9._-]{20,}', + '-----BEGIN (RSA |EC |OPENSSH )?PRIVATE KEY-----', + 'AKIA[0-9A-Z]{16}', # AWS access key + 'ghp_[A-Za-z0-9]{36}', # GitHub personal token + 'ghs_[A-Za-z0-9]{36}', # GitHub server token + 'sk-[A-Za-z0-9]{48}', # OpenAI key + 'DefaultEndpointsProtocol=https.*AccountKey=', # Azure Storage connection string + 'Server=.*Password=' # DB connection string with password +) + +foreach ($pattern in $patterns) { + if ($content -match $pattern) { + Write-Error "BLOCKED: Possible secret detected matching pattern: $pattern" + exit 1 + } +} + +exit 0 diff --git a/.claude/hooks/check-context.ps1 b/.claude/hooks/check-context.ps1 new file mode 100644 index 0000000..2c3d7f6 --- /dev/null +++ b/.claude/hooks/check-context.ps1 @@ -0,0 +1,98 @@ +# Context watcher for Claude Code (UserPromptSubmit hook). +# +# When the active session's input context exceeds THRESHOLD tokens, injects a +# system reminder telling Claude to write a memory dump and prompt the user +# to /clear. The user does the /clear themselves; this script never blocks +# the prompt. +# +# INSTALL: copy to ~/.claude/hooks/check-context.ps1 +# Register in ~/.claude/settings.json under hooks.UserPromptSubmit (see +# settings.user-level.json.template in this directory). +# +# Failure mode: any error → exit 0 silently. The user's prompt is never +# delayed by a parsing or IO problem here. + +$THRESHOLD = 90000 + +try { + $stdin = [Console]::In.ReadToEnd() + if ([string]::IsNullOrWhiteSpace($stdin)) { exit 0 } + + $hookInput = $stdin | ConvertFrom-Json -ErrorAction Stop + $transcriptPath = $hookInput.transcript_path + if ([string]::IsNullOrWhiteSpace($transcriptPath) -or ` + -not (Test-Path -LiteralPath $transcriptPath)) { + exit 0 + } + + $lines = [System.IO.File]::ReadAllLines($transcriptPath) + if ($lines.Count -eq 0) { exit 0 } + + # Walk backwards to find the most recent assistant turn that recorded + # token usage. Total context = input_tokens + cache_creation + cache_read. + $tokens = 0 + for ($i = $lines.Count - 1; $i -ge 0; $i--) { + $line = $lines[$i] + if ([string]::IsNullOrWhiteSpace($line)) { continue } + + try { + $entry = $line | ConvertFrom-Json -ErrorAction Stop + } catch { continue } + + $usage = $entry.message.usage + if (-not $usage) { $usage = $entry.usage } + if (-not $usage) { continue } + if (-not $usage.input_tokens) { continue } + + $cacheCreate = if ($usage.cache_creation_input_tokens) { + [int]$usage.cache_creation_input_tokens + } else { 0 } + $cacheRead = if ($usage.cache_read_input_tokens) { + [int]$usage.cache_read_input_tokens + } else { 0 } + $tokens = [int]$usage.input_tokens + $cacheCreate + $cacheRead + break + } + + # Fallback: char-count / 4 if no usage telemetry found (very early + # in a session, or if the schema changed). + if ($tokens -eq 0) { + $totalChars = 0 + foreach ($line in $lines) { $totalChars += $line.Length } + $tokens = [int]($totalChars / 4) + } + + if ($tokens -lt $THRESHOLD) { exit 0 } + + $tokensK = [math]::Round($tokens / 1000) + $thresholdK = [math]::Round($THRESHOLD / 1000) + + $msg = @" +[CONTEXT-WATCH] Session context: ~${tokensK}k tokens (threshold: ${thresholdK}k). + +Before responding to the user's actual message, write a comprehensive memory dump covering everything from this session that should survive a /clear: in-flight work (branches, files, PR/issue numbers, mid-implementation state), decisions made and their reasoning, bugs found and fixes applied, blockers, open questions, verification status, and any user feedback or preferences observed. + +Write to this project's auto-memory directory (the path is in the auto-memory section of your system prompt). Use existing categories (project / feedback / user / reference) and your judgement on granularity — broad is better than narrow. Update MEMORY.md. + +End your turn with this exact line: +"Memory saved (N files updated). Run /clear when ready — your next session will auto-load." + +The user has explicitly chosen to handle /clear themselves. Do NOT attempt to clear the session or run any harness command yourself. + +If this reminder fires again on a subsequent turn (because /clear hasn't happened yet), append/update incrementally — don't rewrite from scratch. +"@ + + $output = @{ + hookSpecificOutput = @{ + hookEventName = "UserPromptSubmit" + additionalContext = $msg + } + } | ConvertTo-Json -Depth 4 -Compress + + [Console]::Out.Write($output) + exit 0 +} +catch { + # Fail open — never block the user. + exit 0 +} diff --git a/.claude/hooks/format-on-write.ps1 b/.claude/hooks/format-on-write.ps1 new file mode 100644 index 0000000..aa95946 --- /dev/null +++ b/.claude/hooks/format-on-write.ps1 @@ -0,0 +1,47 @@ +# PostToolUse hook — format-on-write +# Fires on Write|Edit. Extracts the file path and applies a formatter if one is configured. +# +# Current behavior: +# .ps1 — skip (no PS formatter configured) +# .md — skip (no markdown formatter configured) +# .ts/.js — runs prettier if available (uncomment below) +# .py — runs black if available (uncomment below) +# +# To add a formatter: uncomment the relevant block and adjust the command. + +$input_json = $input | Out-String +try { $payload = $input_json | ConvertFrom-Json } catch { exit 0 } + +$filePath = if ($payload.file_path) { $payload.file_path } + elseif ($payload.tool_input.file_path) { $payload.tool_input.file_path } + else { exit 0 } + +if (-not $filePath) { exit 0 } + +$ext = [System.IO.Path]::GetExtension($filePath).TrimStart('.').ToLower() + +switch ($ext) { + 'ps1' { + # PowerShell: skip + } + 'md' { + # Markdown: skip (no formatter configured) + } + { $_ -in @('ts', 'tsx', 'js', 'jsx') } { + # TypeScript/JavaScript: uncomment to enable prettier + # if (Get-Command prettier -ErrorAction SilentlyContinue) { + # prettier --write $filePath 2>$null + # } + } + 'py' { + # Python: uncomment to enable black + # if (Get-Command black -ErrorAction SilentlyContinue) { + # black $filePath 2>$null + # } + } + default { + # Plug in your formatter here for other file types. + } +} + +exit 0 diff --git a/.claude/hooks/log-tokens.ps1 b/.claude/hooks/log-tokens.ps1 new file mode 100644 index 0000000..682c523 --- /dev/null +++ b/.claude/hooks/log-tokens.ps1 @@ -0,0 +1,21 @@ +# PostToolUse hook — logs tool usage to .claude/logs/tokens.jsonl +# Event: PostToolUse Write|Edit +# Input: JSON from stdin { tool_name, tool_input, tool_response } +# Configure: set $logDir to your repo's .claude/logs/ path + +$logDir = "D:\git\azurelocal\platform\.claude\logs" + +$input_json = $input | Out-String +try { $payload = $input_json | ConvertFrom-Json } catch { exit 0 } + +if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir -Force | Out-Null } + +$entry = @{ + timestamp = (Get-Date -Format 'o') + tool_name = $payload.tool_name + file_path = $payload.tool_input.file_path + session_id = $env:CLAUDE_SESSION_ID +} | ConvertTo-Json -Compress + +Add-Content -Path "$logDir\tokens.jsonl" -Value $entry -Encoding UTF8 +exit 0 diff --git a/.claude/hooks/summarize-session.ps1 b/.claude/hooks/summarize-session.ps1 new file mode 100644 index 0000000..890c779 --- /dev/null +++ b/.claude/hooks/summarize-session.ps1 @@ -0,0 +1,16 @@ +# Stop hook — logs session end event to .claude/logs/sessions.jsonl +# Event: Stop +# Configure: set $logDir to your repo's .claude/logs/ path + +$logDir = "D:\git\azurelocal\platform\.claude\logs" + +if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir -Force | Out-Null } + +$entry = @{ + timestamp = (Get-Date -Format 'o') + event = "session_stop" + session_id = $env:CLAUDE_SESSION_ID +} | ConvertTo-Json -Compress + +Add-Content -Path "$logDir\sessions.jsonl" -Value $entry -Encoding UTF8 +exit 0 diff --git a/.claude/hooks/validate-path.ps1 b/.claude/hooks/validate-path.ps1 new file mode 100644 index 0000000..13fd984 --- /dev/null +++ b/.claude/hooks/validate-path.ps1 @@ -0,0 +1,31 @@ +# PreToolUse hook — blocks writes to protected paths +# Event: PreToolUse Write|Edit +# Input: JSON from stdin { tool_name, tool_input: { file_path } } + +$input_json = $input | Out-String +try { $payload = $input_json | ConvertFrom-Json } catch { exit 0 } + +$filePath = $payload.tool_input.file_path +if (-not $filePath) { exit 0 } + +$normalizedPath = $filePath.Replace('\', '/').ToLower() + +# Add or remove paths as needed for your repo +$blocked = @( + '/.git/', + '/node_modules/', + '/dist/', + '/.env', + '/dist-ssr/', + '/.next/', + '/build/' +) + +foreach ($b in $blocked) { + if ($normalizedPath -like "*$b*") { + Write-Error "BLOCKED: Write to protected path: $filePath (matched: $b)" + exit 1 + } +} + +exit 0 diff --git a/.claude/settings.json b/.claude/settings.json index 947646f..1975868 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -1,99 +1,58 @@ { + "env": { + "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1" + }, + "hooks": { + "PreToolUse": [ + { + "matcher": "Write|Edit", + "hooks": [ + { "type": "command", "command": "pwsh -NonInteractive -File D:/git/azurelocal/platform/.claude/hooks/block-secrets.ps1" }, + { "type": "command", "command": "pwsh -NonInteractive -File D:/git/azurelocal/platform/.claude/hooks/validate-path.ps1" } + ] + } + ], + "PostToolUse": [ + { + "matcher": "Write|Edit", + "hooks": [ + { "type": "command", "command": "pwsh -NonInteractive -File D:/git/azurelocal/platform/.claude/hooks/log-tokens.ps1" } + ] + } + ], + "Stop": [ + { + "hooks": [ + { "type": "command", "command": "pwsh -NonInteractive -File D:/git/azurelocal/platform/.claude/hooks/summarize-session.ps1" } + ] + } + ] + }, "permissions": { "allow": [ - "Bash(python3 -c ':*)", - "Bash(powershell.exe -NonInteractive -Command ':*)", - "Bash(pwsh -NonInteractive -Command ':*)", - "Bash(explorer.exe 'C:\\\\S2DCartographer\\\\maproom-v1.4.0-preview')", - "Bash(python3 build_healthy.py)", - "Bash(sed -i 's/8-stage theoretical capacity waterfall/7-stage theoretical capacity waterfall/g' Modules/Public/Get-S2DCapacityWaterfall.ps1)", - "Bash(sed -i 's/8-stage capacity waterfall horizontal bar/7-stage capacity waterfall horizontal bar/g' Modules/Public/New-S2DDiagram.ps1)", - "Bash(sed -i 's/3. Compute the 8-stage capacity waterfall/3. Compute the 7-stage capacity waterfall/g' Modules/Public/Invoke-S2DCartographer.ps1)", - "Bash(git commit -m ':*)", - "Bash(sed -i -e 's/The 8-stage capacity accounting model./The 7-stage theoretical capacity model./' -e 's/| `UsableCapacity` | \\\\[`S2DCapacity`\\\\]\\(#s2dcapacity\\) | Stage 8 |/| `UsableCapacity` | [`S2DCapacity`]\\(#s2dcapacity\\) | Stage 7 \\(pipeline terminus\\) |/' docs/schema/cluster-snapshot.md)", - "Bash(sed -i -e 's/Horizontal bar diagram showing all 8 stages of capacity consumption. Each stage shows the cumulative remaining capacity with a delta arrow for the deduction at that stage. Status color-coding: green \\(OK\\), amber \\(Warning\\), red \\(Critical\\)./Horizontal bar diagram showing all 7 stages of the theoretical capacity pipeline. Each stage shows the cumulative remaining capacity and the deduction at that stage./' -e 's/Stage 8 Final Usable ██████████ 13.97 TiB/Stage 7 Usable Capacity ██████████ 13.97 TiB/' docs/diagrams.md)", - "Bash(sed -i -e 's/```\\\\nA standalone SVG waterfall diagram generated by `New-S2DDiagram -DiagramType Waterfall`. Shows the 8-stage pipeline from raw physical to final usable capacity as a descending bar chart./```\\\\nA standalone SVG waterfall diagram generated by `New-S2DDiagram -DiagramType Waterfall`. Shows the 7-stage theoretical pipeline from raw physical to final usable capacity as a descending bar chart./' docs/samples.md)", - "Bash(sed -i 's/# 8-stage capacity waterfall/# 7-stage capacity waterfall/' docs/getting-started.md)", - "Bash(powershell -Command ':*)", - "Read(//c/Users/KristopherTurner/Desktop/20260413-2347/**)", - "Bash(\"C:/Program Files/GitHub CLI/gh.exe\" release create v2.6.4 -R AzureLocal/azurelocal-ranger --target main --title \"v2.6.4 — First-Run UX Patch\" --notes-file E:/tmp/v2.6.4-release-body.md)", - "Bash(\"C:/Program Files/GitHub CLI/gh.exe\" issue close 300 -R AzureLocal/azurelocal-ranger)", - "Bash(\"C:/Program Files/GitHub CLI/gh.exe\" api --method PATCH repos/AzureLocal/azurelocal-ranger/milestones/31 -f state=closed)", - "Bash(\"C:/Program Files/GitHub CLI/gh.exe\" run list -R AzureLocal/azurelocal-ranger --workflow publish-psgallery.yml --limit 2)", - "Bash(\"C:/Program Files/GitHub CLI/gh.exe\" run view 24592874146 -R AzureLocal/azurelocal-ranger --log-failed)", - "Bash(\"C:/Program Files/GitHub CLI/gh.exe\" run view 24592874146 -R AzureLocal/azurelocal-ranger)", - "Bash(pwsh -Command \"Find-Module AzureLocalRanger -Repository PSGallery | Select-Object Version, PublishedDate\")", - "Bash(\"C:/Program Files/GitHub CLI/gh.exe\" run list -R AzureLocal/azurelocal-ranger --workflow=publish-psgallery.yml --limit=5)", - "Bash(\"C:/Program Files/GitHub CLI/gh.exe\" run list -R AzureLocal/azurelocal-ranger --workflow=deploy-docs.yml --limit=5)", - "Bash(\"C:/Program Files/GitHub CLI/gh.exe\" run view 24592874190 -R AzureLocal/azurelocal-ranger --log-failed)", - "Bash(\"C:/Program Files/GitHub CLI/gh.exe\" run view 24592874190 -R AzureLocal/azurelocal-ranger)", - "Bash(\"C:/Program Files/GitHub CLI/gh.exe\" api repos/AzureLocal/azurelocal-ranger/contents/.github/workflows/deploy-docs.yml --jq '.content')", - "Bash(python3 -c \"import sys,base64; print\\(base64.b64decode\\(sys.stdin.read\\(\\).replace\\('\\\\\\\\n',''\\)\\).decode\\(\\)\\)\")", - "Bash(dir \"e:/git/azurelocal-ranger/.github/workflows/\")", - "Bash('C:/Program Files/GitHub CLI/gh.exe' issue create -R AzureLocal/azurelocal-ranger --milestone 32 --title '[BUG] Credential prompt gives no format guidance; WinRM service start fires interactively mid-flow' --body ' *)", - "Bash('C:/Program Files/GitHub CLI/gh.exe' issue create -R AzureLocal/azurelocal-ranger --title '[BUG] Credential prompt gives no format guidance; WinRM service start fires interactively mid-flow' --body-file e:/tmp/issue-301-body.md)", - "Bash(\"C:/Program Files/GitHub CLI/gh.exe\" api repos/AzureLocal/azurelocal-ranger/issues/301 -X PATCH -F milestone=32)", - "Bash(\"C:/Program Files/GitHub CLI/gh.exe\" api repos/AzureLocal/azurelocal-ranger/issues/301 -X PATCH -F milestone=32 --jq '.milestone.title')", - "Bash('C:/Program Files/GitHub CLI/gh.exe' issue comment 301 -R AzureLocal/azurelocal-ranger --body '## Additional finding — cluster and domain credentials prompt separately despite documented reuse intent *)", - "Bash(\"C:/Program Files/GitHub CLI/gh.exe\" issue list -R AzureLocal/azurelocal-ranger --state all --search \"spectre\" --json number,title,state,milestone)", - "Bash(\"C:/Program Files/GitHub CLI/gh.exe\" issue list -R AzureLocal/azurelocal-s2d-cartographer --state all --search \"spectre\" --json number,title,state,milestone)", - "Bash(\"C:/Program Files/GitHub CLI/gh.exe\" issue list -R thisismydemo/azure-scout --state all --search \"spectre\" --json number,title,state,milestone)", - "Bash(\"C:/Program Files/GitHub CLI/gh.exe\" api repos/AzureLocal/azurelocal-s2d-cartographer/milestones --jq '.[] | [.number, .title, .state] | @tsv')", - "Bash(\"C:/Program Files/GitHub CLI/gh.exe\" api repos/thisismydemo/azure-scout/milestones --jq '.[] | [.number, .title, .state] | @tsv')", - "Bash('C:/Program Files/GitHub CLI/gh.exe' issue create -R AzureLocal/azurelocal-s2d-cartographer --title '[FEATURE] Integrate PwshSpectreConsole for rich terminal TUI progress display' --body-file e:/tmp/spectre-s2d.md)", - "Bash(\"C:/Program Files/GitHub CLI/gh.exe\" api repos/AzureLocal/azurelocal-s2d-cartographer/issues/70 -X PATCH -F milestone=12 --jq '.milestone.title')", - "Bash('C:/Program Files/GitHub CLI/gh.exe' issue create -R thisismydemo/azure-scout --title '[FEATURE] Integrate PwshSpectreConsole for rich terminal TUI progress display' --body-file e:/tmp/spectre-scout.md)", - "Bash(Get-ChildItem \"C:\\\\AzureLocalRanger\\\\tplabs-clus01-current-state-20260418T010217Z\")", - "Read(//c/AzureLocalRanger/tplabs-clus01-current-state-20260418T010217Z/**)", - "Bash('C:/Program Files/GitHub CLI/gh.exe' issue create -R AzureLocal/azurelocal-ranger --title '[BUG] Node WinRM connections use short names instead of FQDNs — 0x8009030e Kerberos failures on all nodes' --body-file e:/tmp/issue-node-fqdn.md)", - "Bash('C:/Program Files/GitHub CLI/gh.exe' issue create -R AzureLocal/azurelocal-ranger --title '[BUG] Azure Arc node discovery extracts short names only — must extract properties.dnsFqdn to resolve WinRM 0x8009030e failures' --body-file e:/tmp/issue-arc-fqdn.md)", - "Bash('C:/Program Files/GitHub CLI/gh.exe' issue create -R AzureLocal/azurelocal-ranger --title '[BUG] Cluster auto-selection is silent — no notification or selection menu shown to operator' --body-file e:/tmp/issue-cluster-select-ux.md)", - "Bash('C:/Program Files/GitHub CLI/gh.exe' issue create -R AzureLocal/azurelocal-ranger --title '[BUG] Azure discovery must run as a complete first phase before any on-prem WinRM collection begins' --body-file e:/tmp/issue-azure-first.md)", - "Bash(\"C:/Program Files/GitHub CLI/gh.exe\" api repos/AzureLocal/azurelocal-ranger/issues/308 -X PATCH -F milestone=32 --jq '.number,.milestone.title')", - "Bash(\"C:/Program Files/GitHub CLI/gh.exe\" api repos/AzureLocal/azurelocal-ranger/issues/309 -X PATCH -F milestone=32 --jq '.number,.milestone.title')", - "Bash(\"C:/Program Files/GitHub CLI/gh.exe\" api repos/AzureLocal/azurelocal-ranger/issues/310 -X PATCH -F milestone=32 --jq '.number,.milestone.title')", - "Bash(\"C:/Program Files/Git/bin/git.exe\" add docs/project/roadmap.md)", - "Bash('C:/Program Files/Git/bin/git.exe' commit -m 'docs\\(roadmap\\): add v2.6.5, v2.8.0; add #307 s2d-style reporting to v2.7.0 *)", - "Bash(\"C:/Program Files/Git/bin/git.exe\" push)", - "Bash(powershell -Command \"Set-Location 'e:\\\\git\\\\azurelocal-ranger'; git diff --stat\")", - "Read(//usr/local/**)", - "Bash(\"C:\\\\Program Files\\\\Git\\\\cmd\\\\git.exe\" -C \"e:\\\\git\\\\azurelocal-ranger\" add Modules/Private/55-DiscoveryResolvers.ps1)", - "Bash('C:\\\\Program Files\\\\Git\\\\cmd\\\\git.exe' -C 'e:\\\\git\\\\azurelocal-ranger' commit -m 'fix\\(#306\\): resolve short names to FQDNs inside Resolve-RangerNodeInventory *)", - "Bash(\"C:\\\\Program Files\\\\GitHub CLI\\\\gh.exe\" issue edit 311 --repo AzureLocal/azurelocal-ranger --milestone \"v2.6.5 — Credential UX\")", - "Bash(\"C:\\\\Program Files\\\\GitHub CLI\\\\gh.exe\" issue close 311 --repo AzureLocal/azurelocal-ranger --reason completed)", - "Bash(\"C:\\\\Program Files\\\\GitHub CLI\\\\gh.exe\" issue view 36 --repo AzureLocal/azurelocal-ranger)", - "Bash(\"C:\\\\Program Files\\\\Git\\\\cmd\\\\git.exe\" -C \"e:\\\\git\\\\azurelocal-ranger\" add Modules/Public/10-Commands.ps1 Modules/Private/20-Config.ps1)", - "Bash('C:\\\\Program Files\\\\Git\\\\cmd\\\\git.exe' -C 'e:\\\\git\\\\azurelocal-ranger' commit -m 'fix\\(#314\\): add -NetworkDeviceConfigs parameter to Invoke-AzureLocalRanger *)", - "Bash('C:\\\\Program Files\\\\GitHub CLI\\\\gh.exe' issue comment 314 --repo AzureLocal/azurelocal-ranger --body 'Fixed in commit 792fff6 \\(v2.6.5\\). *)", - "Bash(\"C:\\\\Program Files\\\\GitHub CLI\\\\gh.exe\" issue close 314 --repo AzureLocal/azurelocal-ranger --reason completed)", - "Bash(\"C:\\\\Program Files\\\\GitHub CLI\\\\gh.exe\" issue view 313 --repo AzureLocal/azurelocal-ranger --json number,title,milestone)", - "Bash(command -v gh)", - "Bash(/usr/bin/gh --version)", - "Read(//usr/**)", - "Bash(\"C:/Program Files/GitHub CLI/gh.exe\" issue list --repo AzureLocal/azurelocal-ranger --milestone \"v2.6.5\" --state open --json number,title)", - "Bash(\"C:/Program Files/GitHub CLI/gh.exe\" issue list --repo AzureLocal/azurelocal-ranger --milestone \"v2.6.5\" --json number,title)", - "Bash(\"C:/Program Files/GitHub CLI/gh.exe\" api repos/AzureLocal/azurelocal-ranger/milestones)", - "Bash('C:/Program Files/GitHub CLI/gh.exe' issue close 322 --repo AzureLocal/azurelocal-ranger --comment 'Fixed in Modules/Public/10-Commands.ps1, Modules/Private/20-Config.ps1, and Modules/Core/20-Runtime.ps1. -Debug/-Verbose now detected via $PSBoundParameters.ContainsKey\\(\\) in Invoke-AzureLocalRanger and injected as LogLevel='\\\\''debug'\\\\'' through structural overrides into config.behavior.logLevel. The unreliable $callerWantsDebug preference-variable check in the runtime is removed.')", - "Bash(\"C:/Program Files/GitHub CLI/gh.exe\" issue close 326 --repo AzureLocal/azurelocal-ranger --comment \"Fixed in Modules/Core/20-Runtime.ps1 — BMC credential is now prompted immediately after the iDRAC IP entry and stored in CredentialOverrides.bmc before Resolve-RangerCredentialMap runs. Cluster/domain prompts follow after.\")", - "Bash(powershell.exe -NoProfile -Command \"Get-Command gh -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Source\")", - "Bash(cmd.exe /c \"gh --version\")", - "Bash('/c/Program Files/GitHub CLI/gh.exe' issue create --repo AzureLocal/azurelocal-ranger --milestone 32 --label bug --title '[BUG] BMC Redfish 401 Unauthorized on all nodes — Invoke-RestMethod missing -Authentication Basic' --body ' *)", - "Bash('/c/Program Files/GitHub CLI/gh.exe' issue create --repo AzureLocal/azurelocal-ranger --milestone 'v2.6.5 — Credential UX' --label bug --title '[BUG] BMC Redfish 401 Unauthorized on all nodes — Invoke-RestMethod missing -Authentication Basic' --body-file e:/tmp/issue_a_body.txt)", - "Bash('/c/Program Files/GitHub CLI/gh.exe' issue create --repo AzureLocal/azurelocal-ranger --milestone 'v2.6.5 — Credential UX' --label bug --title '[BUG] Invoke-AzureLocalRanger prints raw ordered hashtable to console when result is not assigned' --body-file e:/tmp/issue_b_body.txt)", - "Bash('/c/Program Files/GitHub CLI/gh.exe' issue create --repo AzureLocal/azurelocal-ranger --milestone 'v2.6.5 — Credential UX' --label bug --title '[BUG] WAF rule SEC-007 warns \"references undefined or null calculation '\\\\''amaCoveragePct'\\\\''\" when Arc extensions data is absent' --body-file e:/tmp/issue_c_body.txt)", - "Bash(\"/c/Program Files/Git/bin/rm.exe\" -f \"e:/tmp/issue_a_body.txt\" \"e:/tmp/issue_b_body.txt\" \"e:/tmp/issue_c_body.txt\")", - "Bash('/c/Program Files/GitHub CLI/gh.exe' issue close 327 --repo AzureLocal/azurelocal-ranger --comment 'Fixed in `Modules/Private/55-DiscoveryResolvers.ps1` — `$subscriptionId` and `$clusterRg` in `Resolve-RangerArcMachinesForCluster` now explicitly cast to `[string]` before use, preventing PSCustomObject wrappers from YAML parsing from reaching `Get-AzResource -ResourceGroupName`. Same root cause and fix pattern as #261.')", - "Bash(\"/c/Program Files/GitHub CLI/gh.exe\" issue close 329 --repo AzureLocal/azurelocal-ranger --comment \"Fixed in \\\\`Modules/Private/40-Execution.ps1\\\\` — \\\\`Invoke-RangerRedfishRequest\\\\` now passes \\\\`-Authentication Basic\\\\` to \\\\`Invoke-RestMethod\\\\`. iDRAC Redfish requires Basic auth; without it PowerShell 7 sent Negotiate headers which iDRAC rejected with 401 on every request.\")", - "Bash(\"/c/Program Files/GitHub CLI/gh.exe\" issue close 330 --repo AzureLocal/azurelocal-ranger --comment \"Fixed in \\\\`Modules/Public/10-Commands.ps1\\\\` — \\\\`Invoke-AzureLocalRanger\\\\` now captures the \\\\`Invoke-RangerDiscoveryRuntime\\\\` return value and emits a clean \\\\`Write-Host\\\\` summary \\(collector outcomes + output path + log path\\) instead of allowing the raw ordered hashtable to fall through to the pipeline.\")", - "Bash('/c/Program Files/GitHub CLI/gh.exe' issue close 331 --repo AzureLocal/azurelocal-ranger --comment 'Fixed in `Modules/Collectors/70-WafAssessmentCollector.ps1` — null-calculation handling now checks `$calculations.Contains\\(\\)`: if the key exists but resolved to null \\(data unavailable — e.g. AMA not deployed\\) it logs at debug level; if the key is entirely missing from the calculations dict \\(rule authoring error\\) it keeps the `Write-Warning`. SEC-007 amaCoveragePct will no longer appear as a terminal warning on runs where AMA is absent.')", - "Bash(export PATH=\"$PATH:/usr/bin:/bin:/mingw64/bin:/c/Program Files/GitHub CLI:/c/Users/KristopherTurner/AppData/Local/Programs/GitHub CLI\")", - "Bash(export PATH=\"$PATH:/c/Program Files/GitHub CLI:/c/Users/KristopherTurner/AppData/Local/Programs/GitHub CLI\")", - "Bash(export PATH=\"$PATH:/usr/local/bin:/usr/bin:/bin:/mingw64/bin:/c/Program Files/GitHub CLI\")", - "Bash(gh --version)", - "Bash(powershell.exe -Command \"gh --version\")", - "Bash(powershell.exe -Command \"gh issue create --repo AzureLocal/azurelocal-ranger --title 'Network device config report sections missing — switchConfig/firewallConfig collected but never rendered' --body 'switchConfig and firewallConfig are collected into the manifest via -NetworkDeviceConfigs but no report section renders them. Fix: add Imported Switch Configurations and Imported Firewall Configurations table sections to Get-RangerReportSections in Modules/Outputs/Reports/10-Reports.ps1.' --milestone 'v2.6.5'\")", - "Read(//mnt/c/Windows/**)", - "Bash(export PATH=\"$PATH:/mnt/c/Program Files/GitHub CLI\")" + "Bash(git add:*)", + "Bash(git commit -m \':*)", + "Bash(git commit:*)", + "Bash(git push:*)", + "Bash(git status:*)", + "Bash(git log:*)", + "Bash(git diff:*)", + "Bash(pwsh -NoProfile -Command \':*)", + "Bash(pwsh -NoProfile -File \':*)", + "Bash(pwsh -NonInteractive -Command \':*)", + "Bash(pwsh -NonInteractive -File \':*)", + "Bash(gh issue:*)", + "Bash(gh pr:*)", + "Bash(gh run:*)", + "Bash(gh api:*)", + "Bash(gh workflow:*)", + "Bash(gh release:*)", + "Read(//d/git/azurelocal/platform/**)", + "WebSearch", + "WebFetch(domain:github.com)", + "WebFetch(domain:raw.githubusercontent.com)", + "WebFetch(domain:learn.microsoft.com)", + "WebFetch(domain:dev.azure.com)" ] } } diff --git a/.codex/config.toml b/.codex/config.toml new file mode 100644 index 0000000..0e3c206 --- /dev/null +++ b/.codex/config.toml @@ -0,0 +1,12 @@ +# Codex project config for azurelocal-platform +# Codex reads repo-level config from .codex/config.toml in trusted projects. +# Codex has no agent-definition files and no hook system — do not add either. +# Repo instructions live in AGENTS.md, which Codex reads natively. + +# HCS Governance MCP — remote Streamable HTTP server. +# Older Codex builds require enabling the rmcp client for HTTP servers; +# uncomment the next line if your Codex version does not connect over url alone: +# experimental_use_rmcp_client = true + +[mcp_servers.hcs-governance] +url = "https://mcp.hybridsolutions.cloud/mcp" diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..7ddcc8f --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,6 @@ +# azurelocal-platform — Copilot instructions + +Read [`AGENTS.md`](../AGENTS.md) at the repo root for full repo context, hard rules, +and the HCS Governance MCP bootstrap instruction. Follow the `.ai/` session protocol +described there: read `.ai/state/*` at session start and update `.ai/state/HANDOFF.md` +before ending a session. diff --git a/.gitignore b/.gitignore index ea902ec..8e2748b 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,5 @@ temp/ out/ dist/ *.log + +.claude/logs/ diff --git a/.mcp.json b/.mcp.json new file mode 100644 index 0000000..4dd5f3e --- /dev/null +++ b/.mcp.json @@ -0,0 +1,8 @@ +{ + "mcpServers": { + "hcs-governance": { + "type": "http", + "url": "https://mcp.hybridsolutions.cloud/mcp" + } + } +} diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..aba6e4f --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,80 @@ +# azurelocal-platform — Agent instructions + + + +## What this repo is + +Repo in the HCS estate managed under the platform engineering standard. + + + +--- + +## Start here — connect to the HCS Governance MCP + +This repo is governed by the **HCS Governance MCP server** (connection details in +[`.ai/mcp/mcp-servers.md`](.ai/mcp/mcp-servers.md)). It is the source of truth for +standards, hard rules, and orchestration guidance. + +**At session start, call:** + +``` +bootstrap(repo="azurelocal-platform", client="") +``` + +It returns this repo's scope, the applicable hard rules, the index of applicable +standards, the `.ai/` session protocol, and orchestration guidance shaped for your +client's capability tier. **Prefer a live MCP answer over anything written in this file** — +this file is the offline fallback. + +--- + +## Offline fallback (when the MCP server is unreachable) + +**Standards scope:** `azurelocal` + +**Hard rules digest:** + +- No secrets, tokens, passwords, subscription/tenant/client IDs, or connection strings in any committed file. +- All scripts: PowerShell 7+ — `#Requires -Version 7.0`, `Set-StrictMode -Version Latest`, `$ErrorActionPreference = 'Stop'`. Never PS 5.1, never Bash. +- All documentation is Markdown only. Diagrams are draw.io only — commit the `.drawio` XML alongside any exported `.png`. +- Commit format: `type(scope): short description` — types `feat`, `fix`, `docs`, `chore`, `refactor`, `test` — with an `AB#` work-item reference. + +**Standards reference (public site — no auth required):** + +- Governance — +- Scripting — +- Automation — +- Documentation — +- Agents (multi-model) — +- AI workspace — +- Full index — + +--- + +## Session protocol + +1. **Read `.ai/state/` first** — `CURRENT_TASK.md`, then `HANDOFF.md`, then `OPEN_QUESTIONS.md`. +2. Then read `.ai/memory/` for durable context (`PROJECT_CONTEXT.md`, `DECISIONS.md`, `COMMANDS.md`, `GOTCHAS.md`). +3. Summarise your believed state back to the operator before making changes. +4. **Before ending the session, update `.ai/state/HANDOFF.md`** — what changed, files touched, commands run and results, branch, blockers, next steps. + +Full contract: the [AI workspace standard](https://platform.hybridsolutions.cloud/standards/ai-workspace/). + +--- + +## Key facts + +| Fact | Value | +|---|---| +| ADO org | | +| ADO project | N/A - see registry.yaml `ado_project` or ask the HCS Governance MCP `get_repo` for this repo's work-item tracking project | +| Area path | N/A - see registry.yaml or ask the HCS Governance MCP | +| Key Vault | kv-hcs-vault-01 | +| Work item format | `AB#` in commits and PRs | diff --git a/CLAUDE.md b/CLAUDE.md index 5205239..66dac40 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,157 +1,32 @@ -# platform — Claude Code Context +# azurelocal-platform — Claude Code -## What this repo is +@AGENTS.md -[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE) -[![Docs](https://img.shields.io/badge/docs-mkdocs--material-0078D4)](https://AzureLocal.github.io/platform/) + ---- +## Claude Code notes -## ADO project details +- Subagents, skills, and hooks for this repo live in `.claude/`. The repo-level MCP config is `.mcp.json`. +- Use **plan mode** before broad, repo-wide changes. +- Follow the `.ai/` session protocol: read `.ai/state/*` at session start, and update `.ai/state/HANDOFF.md` before ending a session. +- See the [agents standard](https://platform.hybridsolutions.cloud/standards/agents/) for the full multi-model model. -- **ADO org:** https://dev.azure.com/hybridcloudsolutions -- **ADO project:** Azure Local -- **Area path:** Platform Engineering\Onboarding -- **Work item format:** `AB#` in commit messages and PR descriptions ---- - -## Standards - -This repo follows all HCS platform standards defined in the Platform Engineering repo: - -| Standard | Reference | -|---|---| -| Governance | [docs/standards/governance.md](https://dev.azure.com/hybridcloudsolutions/Platform%20Engineering/_git/Platform%20Engineering?path=/docs/standards/governance.md) | -| Scripting (PowerShell 7) | [docs/standards/scripting.md](https://dev.azure.com/hybridcloudsolutions/Platform%20Engineering/_git/Platform%20Engineering?path=/docs/standards/scripting.md) | -| Automation | [docs/standards/automation.md](https://dev.azure.com/hybridcloudsolutions/Platform%20Engineering/_git/Platform%20Engineering?path=/docs/standards/automation.md) | -| Variables and naming | [docs/standards/variables.md](https://dev.azure.com/hybridcloudsolutions/Platform%20Engineering/_git/Platform%20Engineering?path=/docs/standards/variables.md) | -| Documentation | [docs/standards/documentation.md](https://dev.azure.com/hybridcloudsolutions/Platform%20Engineering/_git/Platform%20Engineering?path=/docs/standards/documentation.md) | -| Claude Code | [docs/standards/claude-code.md](https://dev.azure.com/hybridcloudsolutions/Platform%20Engineering/_git/Platform%20Engineering?path=/docs/standards/claude-code.md) | - -Key rules: -- All scripts: PowerShell 7+ only. `#Requires -Version 7.0`, `Set-StrictMode -Version Latest`, ` $ErrorActionPreference = 'Stop'`. -- All docs: Markdown only. No Word documents in any repo. -- Commit format: `type(scope): short description` — types: `feat`, `fix`, `docs`, `chore`, `refactor`, `test` -- No secrets, tokens, or credentials committed to any file. - ---- - -## Key facts - -| Fact | Value | -|---|---| -| Primary language | Markdown / Python (MkDocs) | -| GitHub org | AzureLocal | -| Azure login | kris@hybridsolutions.cloud | -| Key Vault | kv-hcs-vault-01 | - -### Environment variables expected - -| Variable | Source | Purpose | -|---|---|---| -| `GITHUB_TOKEN` | kv-hcs-vault-01 via Load-HCSEnvironment.ps1 | GitHub CLI and git operations | -| `AZURE_DEVOPS_EXT_PAT` | kv-hcs-vault-01 via Load-HCSEnvironment.ps1 | ADO CLI (`az boards`, `az devops`) | -Load before starting a session: -```powershell -. E:\git\platform\scripts\Load-HCSEnvironment.ps1 -``` - -### Build and test commands - -``` -mkdocs build -mkdocs serve # http://127.0.0.1:8000 -``` - ---- - -## Repo structure - -``` -platform/ -├── .claude/ - ├── platform-epic-issue-body.md - ├── scheduled_tasks.lock - └── settings.json -├── .github/ - └── workflows/ -├── decisions/ - ├── 0001-create-platform-repo.md - ├── 0002-standards-single-source.md - ├── 0003-maproom-iic-canon.md - ├── 0004-testing-toolset-classification.md - └── 0005-reusable-workflow-split.md -├── docs/ - ├── contributing/ - ├── getting-started/ - ├── governance/ - ├── maproom/ - └── modules/ -├── modules/ - └── powershell/ -├── repo-management/ - ├── org-scripts/ - └── README.md -├── scripts/ - ├── README.md - └── Seed-DocStubs.ps1 -├── templates/ - ├── _common/ - ├── iac-solution/ - ├── migration-runbook/ - ├── ps-module/ - └── training-site/ -├── testing/ - ├── iic-canon/ - ├── maproom/ - ├── trailhead/ - └── README.md -├── .azurelocal-platform.yml -├── .editorconfig -├── .gitignore -├── .markdownlint.json -├── .release-please-manifest.json -├── .yamllint.yml -├── azurelocal-platform.code-workspace -├── CHANGELOG.md -├── CLAUDE.md -└── ... -``` - ---- - -## Claude Code actions +## Claude Code actions in this repo **Run autonomously:** - Read, search, and grep any file in this repo - Write and edit files in this repo - `git add`, `git commit`, `git push` - `gh issue`, `gh pr`, `gh run` CLI commands -- `mkdocs build` and `mkdocs serve` -- `pip install` for MkDocs plugins **Always confirm before:** - Creating or deleting Azure resources - Any `az` CLI write operation that modifies Azure state - Running destructive operations - Making API calls to external services - - ---- - -## Subagents available in this repo - -- `platform-engineer` (model: sonnet) — Expert in `platform`: deep knowledge of this repo's structure, conventions, and development workflow. - -User-level agents (available in every repo session): `triage-lookup`, `markdown-prose-editor`, `azurelocal-domain-expert`, `mkdocs-material-doctor`, `turner-module-scaffold-engineer`, `mms-2026-demo-presenter`. - ---- - -## Owner - -**Kristopher Turner** -kris@hybridsolutions.cloud -Senior Product Technology Architect, TierPoint | Microsoft MVP (Azure) | MCT -Owner, Hybrid Cloud Solutions LLC — hybridsolutions.cloud -Country Cloud Boy — thisismydemo.cloud \ No newline at end of file +- Installing software From 36bb5fcff168e65bd96553058fcef238e3024d33 Mon Sep 17 00:00:00 2001 From: Kristopher Turner Date: Thu, 16 Jul 2026 13:20:03 -0400 Subject: [PATCH 2/2] docs(standards): add PMO board overlay AB#4945 --- docs/standards/index.md | 1 + docs/standards/project-management.md | 34 ++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 docs/standards/project-management.md diff --git a/docs/standards/index.md b/docs/standards/index.md index f2567b3..d213f6b 100644 --- a/docs/standards/index.md +++ b/docs/standards/index.md @@ -21,6 +21,7 @@ This repository follows the **org-wide AzureLocal standards** maintained on the |----------|-----------|------------------| | Documentation | [Documentation Standards](documentation) | [Full Reference](https://azurelocal.cloud/standards/documentation/documentation-standards) | | Repository Management | [Repository Management Standard](repository-management) | [Full Reference](https://azurelocal.cloud/standards/repository-management/) | +| Project Management | [Project Management](project-management) | [HCS Base Standard](https://platform.hybridsolutions.cloud/standards/project-management/) | | Scripting | [Scripting Standards](scripting) | [Full Reference](https://azurelocal.cloud/standards/scripting/scripting-standards) | | Variables | [Variable Standards](variables) | [Full Reference](https://azurelocal.cloud/standards/variable-management/) | | Naming Conventions | [Naming Conventions](naming) | [Full Reference](https://azurelocal.cloud/standards/documentation/naming-conventions) | diff --git a/docs/standards/project-management.md b/docs/standards/project-management.md new file mode 100644 index 0000000..601ea0a --- /dev/null +++ b/docs/standards/project-management.md @@ -0,0 +1,34 @@ +--- +title: Project Management +description: AzureLocal rules for tracker-authoritative planning and reusable PMO boards. +--- + +# Project Management + +This page is the AzureLocal overlay for the HCS +[project-management standard](https://platform.hybridsolutions.cloud/standards/project-management/). +Only AzureLocal-specific differences are defined here. + +## Authoritative source + +GitHub Issues and the AzureLocal organization Project are the primary intake and work-tracking +surfaces. Issues may synchronize into HCS Azure DevOps under the existing split-source rules, but +operators author and update GitHub-native issue data in GitHub. + +The reusable PMO board is a read-only snapshot of those issues. It MUST NOT store browser edits or +write changes back to GitHub. Every displayed item links to its authoritative issue. + +## Scope selection + +AzureLocal uses the per-repository project model unless `registry.yaml` explicitly assigns a +shared project. A board SHOULD represent one repository. A cross-repository portfolio board MAY +use the organization Project when its configuration names that scope explicitly. + +## Publication + +Generated snapshots stay under ignored `.artifacts/pmo/`. Scheduled automation publishes an +authenticated workflow artifact. Claude or Codex publication remains owner-only or +workspace-restricted unless the repository owner explicitly approves public access. + +See also [Repository Management](repository-management.md) and the HCS +[work-item sync standard](https://platform.hybridsolutions.cloud/standards/work-item-sync/).