From f142e44e24908ed42ed4b05a4744590221b8adf7 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 29 Aug 2026 12:54:45 +0200 Subject: [PATCH 01/19] Define organization context path contract --- tests/Initialize-MsxWorkspace.Tests.ps1 | 114 ++++++++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/tests/Initialize-MsxWorkspace.Tests.ps1 b/tests/Initialize-MsxWorkspace.Tests.ps1 index 65393f1..13f546b 100644 --- a/tests/Initialize-MsxWorkspace.Tests.ps1 +++ b/tests/Initialize-MsxWorkspace.Tests.ps1 @@ -782,4 +782,118 @@ exit `$LASTEXITCODE (Invoke-Git -Arguments @("--git-dir=$backing", 'rev-parse', 'main')).Trim() | Should -BeExactly $remoteHead (Invoke-Git -WorkingDirectory $docs -Arguments @('rev-parse', 'HEAD')).Trim() | Should -BeExactly $remoteHead } + + It 'declares the canonical repositories at their preferred local paths' { + $bootstrapText = Get-Content -LiteralPath $script:bootstrap -Raw + + $expectedRepositories = @( + @{ + Name = 'MSXOrg/docs' + Path = '.msxorg/docs' + Url = 'https://github.com/MSXOrg/docs.git' + } + @{ + Name = 'MSXOrg/memory' + Path = '.msxorg/memory' + Url = 'https://github.com/MSXOrg/memory.git' + } + @{ + Name = 'PSModule/Process-PSModule' + Path = '.psmodule/process-psmodule' + Url = 'https://github.com/PSModule/Process-PSModule.git' + } + @{ + Name = 'PSModule/memory' + Path = '.psmodule/memory' + Url = 'https://github.com/PSModule/memory.git' + } + ) + + foreach ($repository in $expectedRepositories) { + $bootstrapText | Should -Match ([regex]::Escape("Name = '$($repository.Name)'")) + $bootstrapText | Should -Match ([regex]::Escape("Path = '$($repository.Path)'")) + $bootstrapText | Should -Match ([regex]::Escape("Url = '$($repository.Url)'")) + } + $bootstrapText | Should -Not -Match 'PSModule/docs' + $bootstrapText | Should -Not -Match "Join-Path `$HOME '\.msx'" + } + + It 'keeps every router example repository-addressable and access-method neutral' { + $directive = 'Read nearest first, prefer documentation over memory, and always use the newest version.' + $routerPaths = @( + (Join-Path $PSScriptRoot '../AGENTS.md') + (Join-Path $PSScriptRoot '../bootstrap/AGENTS.template.md') + (Join-Path $PSScriptRoot '../src/docs/Capabilities/agentic-development/design.md') + ) + + foreach ($routerPath in $routerPaths) { + $router = Get-Content -LiteralPath $routerPath -Raw + $router | Should -Match ([regex]::Escape($directive)) + $router | Should -Match 'MSXOrg/docs' + $router | Should -Match 'MSXOrg/memory' + $router | Should -Match '~/.msxorg/docs' + $router | Should -Match '~/.msxorg/memory' + } + + $design = Get-Content -LiteralPath $routerPaths[2] -Raw + $design | Should -Match 'PSModule/Process-PSModule' + $design | Should -Match 'PSModule/memory' + $design | Should -Match '~/.psmodule/process-psmodule' + $design | Should -Match '~/.psmodule/memory' + $design | Should -Match 'https://msxorg\.github\.io/docs/' + $design | Should -Match 'https://psmodule\.io/docs/Modules/Process-PSModule/' + $design | Should -Match '(?i)private.+MSXOrg/memory|MSXOrg/memory.+private' + $design | Should -Match '(?i)private.+PSModule/memory|PSModule/memory.+private' + $design | Should -Match '(?i)CLI.+web.+published.+local clone' + } + + It 'ignores former layout content and creates fresh canonical clones with diagnostics' { + $homeRoot = Join-Path $fixture.Root 'migration-home' + $legacyPaths = @( + '.msx/docs' + '.msx/memory' + '.msx/projects/PSModule/docs' + '.msx/projects/PSModule/memory' + ) + foreach ($legacyPath in $legacyPaths) { + $path = Join-Path $homeRoot $legacyPath + New-Item -ItemType Directory -Path $path -Force | Out-Null + Set-Content -LiteralPath (Join-Path $path 'stale.txt') -Value 'must not be trusted' + } + + $runner = Join-Path $fixture.Root 'invoke-layout-migration.ps1' + $bootstrap = $script:bootstrap.Replace("'", "''") + $root = $homeRoot.Replace("'", "''") + $docsRemote = $fixture.Remotes.docs.Replace("'", "''") + $memoryRemote = $fixture.Remotes.memory.Replace("'", "''") + @" +`$repositories = @( + @{ Name = 'MSXOrg/docs'; Path = '.msxorg/docs'; Url = '$docsRemote'; Kind = 'docs' } + @{ Name = 'MSXOrg/memory'; Path = '.msxorg/memory'; Url = '$memoryRemote'; Kind = 'memory' } + @{ Name = 'PSModule/Process-PSModule'; Path = '.psmodule/process-psmodule'; Url = '$docsRemote'; Kind = 'docs' } + @{ Name = 'PSModule/memory'; Path = '.psmodule/memory'; Url = '$memoryRemote'; Kind = 'memory' } +) +& '$bootstrap' -Root '$root' -Repository `$repositories -UserName 'Fixture User' -UserEmail 'fixture@example.invalid' +exit `$LASTEXITCODE +"@ | Set-Content -LiteralPath $runner + + $output = & $script:pwsh -NoProfile -File $runner 2>&1 | Out-String + + $LASTEXITCODE | Should -Be 0 -Because $output + $output | Should -Match 'Former context path' + $output | Should -Match 'will not be used' + foreach ($legacyPath in $legacyPaths) { + Test-Path -LiteralPath (Join-Path $homeRoot "$legacyPath/stale.txt") | Should -BeTrue + } + foreach ($canonicalPath in @( + '.msxorg/docs' + '.msxorg/memory' + '.psmodule/process-psmodule' + '.psmodule/memory' + )) { + $path = Join-Path $homeRoot $canonicalPath + Test-Path -LiteralPath (Join-Path $path 'stale.txt') | Should -BeFalse + Test-Path -LiteralPath (Join-Path $path '.git') | Should -BeTrue + } + } } From 61b134b5c8263e21d217cb918f1bce1e6b70f78c Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 29 Aug 2026 13:00:53 +0200 Subject: [PATCH 02/19] Bootstrap canonical organization context repositories --- bootstrap/Initialize-MsxWorkspace.ps1 | 166 ++++++++++++----------- tests/Initialize-MsxWorkspace.Tests.ps1 | 170 ++++++++---------------- 2 files changed, 143 insertions(+), 193 deletions(-) diff --git a/bootstrap/Initialize-MsxWorkspace.ps1 b/bootstrap/Initialize-MsxWorkspace.ps1 index 80ddff9..b587994 100644 --- a/bootstrap/Initialize-MsxWorkspace.ps1 +++ b/bootstrap/Initialize-MsxWorkspace.ps1 @@ -6,10 +6,10 @@ Clone or update canonical project context repositories in a git-isolated workspace under $HOME. .DESCRIPTION - The single starting point for every agent. It ensures the central - documentation and memory repositories for each configured project exist - locally under one dedicated workspace, so an agent reads current canonical - context regardless of which repository it is working in. + The single starting point for every agent. It ensures each configured + canonical context repository exists at its preferred local path under one + dedicated root, so an agent reads current canonical context regardless of + which repository it is working in. The workspace is deliberately kept separate from the repositories an agent works in: @@ -28,23 +28,20 @@ .EXAMPLE ./Initialize-MsxWorkspace.ps1 - Clones missing repositories and exactly synchronizes existing ones under ~/.msx. + Clones or synchronizes the canonical MSXOrg and PSModule context under the + current user's home directory. .EXAMPLE - ./Initialize-MsxWorkspace.ps1 -Root /work/.msx -Verbose - Uses a custom workspace root and logs each step. + ./Initialize-MsxWorkspace.ps1 -Root /work -Verbose + Uses a custom context root and logs each step. .EXAMPLE - $projects = @( - @{ - Name = 'PSModule' - Path = 'projects/PSModule' - DocsUrl = 'https://github.com/PSModule/docs.git' - MemoryUrl = 'https://github.com/PSModule/memory.git' - } + $repositories = @( + @{ Name = 'MSXOrg/docs'; Path = '.msxorg/docs'; Url = 'https://github.com/MSXOrg/docs.git'; Kind = 'docs' } + @{ Name = 'MSXOrg/memory'; Path = '.msxorg/memory'; Url = 'https://github.com/MSXOrg/memory.git'; Kind = 'memory' } ) - ./Initialize-MsxWorkspace.ps1 -Project $projects - Installs a project's docs and memory under a project-specific workspace path. + ./Initialize-MsxWorkspace.ps1 -Repository $repositories + Synchronizes an explicit repository set at explicit paths. .OUTPUTS [pscustomobject] with Repository, Path, BackingPath, and Changes for each @@ -52,10 +49,10 @@ #> [CmdletBinding(SupportsShouldProcess)] param( - # The workspace root under which 'docs' and 'memory' are placed. + # The root under which repository paths are resolved. [Parameter()] [ValidateNotNullOrEmpty()] - [string] $Root = (Join-Path $HOME '.msx'), + [string] $Root = $HOME, # The git author name written to each clone's local config. [Parameter()] @@ -67,15 +64,34 @@ param( [ValidateNotNullOrEmpty()] [string] $UserEmail = 'MariusStorhaug@users.noreply.github.com', - # Projects whose canonical docs and memory repositories must be synchronized. + # Canonical context repositories and their paths relative to Root. [Parameter()] + [Alias('Repository')] [ValidateNotNullOrEmpty()] - [hashtable[]] $Project = @( + [hashtable[]] $Repositories = @( + @{ + Name = 'MSXOrg/docs' + Path = '.msxorg/docs' + Url = 'https://github.com/MSXOrg/docs.git' + Kind = 'docs' + } + @{ + Name = 'MSXOrg/memory' + Path = '.msxorg/memory' + Url = 'https://github.com/MSXOrg/memory.git' + Kind = 'memory' + } + @{ + Name = 'PSModule/Process-PSModule' + Path = '.psmodule/process-psmodule' + Url = 'https://github.com/PSModule/Process-PSModule.git' + Kind = 'docs' + } @{ - Name = 'MSXOrg' - Path = '' - DocsUrl = 'https://github.com/MSXOrg/docs.git' - MemoryUrl = 'https://github.com/MSXOrg/memory.git' + Name = 'PSModule/memory' + Path = '.psmodule/memory' + Url = 'https://github.com/PSModule/memory.git' + Kind = 'memory' } ) ) @@ -278,72 +294,58 @@ function Set-ContextIdentity { if ($LASTEXITCODE -ne 0) { throw "git config user.email failed for '$Path' (exit $LASTEXITCODE)." } } -$projectNames = [Collections.Generic.HashSet[string]]::new([StringComparer]::OrdinalIgnoreCase) -$repositories = foreach ($projectDefinition in $Project) { - foreach ($key in @('Name', 'Path', 'DocsUrl', 'MemoryUrl')) { - if (-not $projectDefinition.ContainsKey($key) -or $null -eq $projectDefinition[$key]) { - throw "Project definitions require Name, Path, DocsUrl, and MemoryUrl. Missing '$key'." +$repositoryNames = [Collections.Generic.HashSet[string]]::new([StringComparer]::OrdinalIgnoreCase) +$contextRepositories = foreach ($repositoryDefinition in $Repositories) { + foreach ($key in @('Name', 'Path', 'Url', 'Kind')) { + if (-not $repositoryDefinition.ContainsKey($key) -or $null -eq $repositoryDefinition[$key]) { + throw "Repository definitions require Name, Path, Url, and Kind. Missing '$key'." } } - $projectName = [string] $projectDefinition.Name - $projectPath = ([string] $projectDefinition.Path).Trim() - if (-not $projectName.Trim()) { - throw 'Project Name must not be empty.' + $repositoryName = ([string] $repositoryDefinition.Name).Trim() + if (-not $repositoryName) { + throw 'Repository Name must not be empty.' } - $projectName = $projectName.Trim() - if (-not $projectNames.Add($projectName)) { - throw "Project definitions require unique names. Duplicate: '$projectName'." + if (-not $repositoryNames.Add($repositoryName)) { + throw "Repository definitions require unique names. Duplicate: '$repositoryName'." } - $pathSegments = @($projectPath -split '[\\/]' | Where-Object { $_ -and $_ -ne '.' }) - if ([IO.Path]::IsPathRooted($projectPath) -or '..' -in $pathSegments) { - throw "Project Path '$projectPath' must be a safe path relative to the workspace root." + + $repositoryPath = ([string] $repositoryDefinition.Path).Trim() + $pathSegments = @($repositoryPath -split '[\\/]' | Where-Object { $_ -and $_ -ne '.' }) + if ( + -not $pathSegments -or + [IO.Path]::IsPathRooted($repositoryPath) -or + '..' -in $pathSegments + ) { + throw "Repository Path '$repositoryPath' must be a non-empty safe path relative to Root." } - $projectPath = $pathSegments -join [IO.Path]::DirectorySeparatorChar + $repositoryPath = $pathSegments -join [IO.Path]::DirectorySeparatorChar - $docsPath = if ($projectPath) { Join-Path $projectPath 'docs' } else { 'docs' } - $memoryPath = if ($projectPath) { Join-Path $projectPath 'memory' } else { 'memory' } - [pscustomobject]@{ - Name = "$projectName/docs" - Project = $projectName - ProjectPath = $projectPath - Kind = 'docs' - RelativePath = $docsPath - Url = [string] $projectDefinition.DocsUrl - Changes = 'pull requests' + $kind = ([string] $repositoryDefinition.Kind).Trim().ToLowerInvariant() + if ($kind -notin @('docs', 'memory')) { + throw "Repository Kind for '$repositoryName' must be 'docs' or 'memory', not '$kind'." } + [pscustomobject]@{ - Name = "$projectName/memory" - Project = $projectName - ProjectPath = $projectPath - Kind = 'memory' - RelativePath = $memoryPath - Url = [string] $projectDefinition.MemoryUrl - Changes = 'repository policy' + Name = $repositoryName + Kind = $kind + RelativePath = $repositoryPath + Url = [string] $repositoryDefinition.Url + Changes = if ($kind -eq 'docs') { 'pull requests' } else { 'repository policy' } } } -$occupiedPaths = foreach ($repository in $repositories) { +$occupiedPaths = foreach ($repository in $contextRepositories) { [pscustomobject]@{ - Project = $repository.Project Repository = $repository.Name Path = $repository.RelativePath } if ($repository.Kind -eq 'docs') { - if ($repository.ProjectPath) { - [pscustomobject]@{ - Project = $repository.Project - Repository = "$($repository.Project) root" - Path = $repository.ProjectPath - } - } [pscustomobject]@{ - Project = $repository.Project Repository = "$($repository.Name) backing" Path = "$($repository.RelativePath).git" } [pscustomobject]@{ - Project = $repository.Project Repository = "$($repository.Name) migration backup" Path = "$($repository.RelativePath).simple-clone-backup" } @@ -352,9 +354,6 @@ $occupiedPaths = foreach ($repository in $repositories) { for ($left = 0; $left -lt $occupiedPaths.Count; $left++) { $leftPath = ($occupiedPaths[$left].Path -replace '\\', '/').Trim('/').ToLowerInvariant() for ($right = $left + 1; $right -lt $occupiedPaths.Count; $right++) { - if ($occupiedPaths[$left].Project -eq $occupiedPaths[$right].Project) { - continue - } $rightPath = ($occupiedPaths[$right].Path -replace '\\', '/').Trim('/').ToLowerInvariant() $collision = ( $leftPath -eq $rightPath -or @@ -362,12 +361,29 @@ for ($left = 0; $left -lt $occupiedPaths.Count; $left++) { $rightPath.StartsWith("$leftPath/", [StringComparison]::Ordinal) ) if ($collision) { - throw "Project workspace paths overlap: '$($occupiedPaths[$left].Path)' and '$($occupiedPaths[$right].Path)'." + throw "Repository paths overlap: '$($occupiedPaths[$left].Path)' and '$($occupiedPaths[$right].Path)'." } } } -foreach ($repository in $repositories | Where-Object Kind -eq 'memory') { +$formerPaths = @{ + 'MSXOrg/docs' = '.msx/docs' + 'MSXOrg/memory' = '.msx/memory' + 'PSModule/Process-PSModule' = '.msx/projects/PSModule/docs' + 'PSModule/memory' = '.msx/projects/PSModule/memory' +} +foreach ($repository in $contextRepositories) { + if (-not $formerPaths.ContainsKey($repository.Name)) { + continue + } + $formerPath = Join-Path $Root $formerPaths[$repository.Name] + if (Test-Path -LiteralPath $formerPath) { + $canonicalPath = Join-Path $Root $repository.RelativePath + Write-Warning "Former context path '$formerPath' for '$($repository.Name)' will not be used. Bootstrap will refresh the canonical repository at '$canonicalPath'. Remove the former path only after verifying the canonical clone." + } +} + +foreach ($repository in $contextRepositories | Where-Object Kind -eq 'memory') { $memoryPath = Join-Path $Root $repository.RelativePath $memoryGitEntry = Join-Path $memoryPath '.git' if (Test-Path $memoryGitEntry -PathType Leaf) { @@ -378,7 +394,7 @@ foreach ($repository in $repositories | Where-Object Kind -eq 'memory') { } } -foreach ($repository in $repositories) { +foreach ($repository in $contextRepositories) { $contextPath = Join-Path $Root $repository.RelativePath $gitEntry = Join-Path $contextPath '.git' if ($repository.Kind -eq 'memory' -and (Test-Path $gitEntry -PathType Container)) { @@ -402,7 +418,7 @@ if ($PSCmdlet.ShouldProcess($Root, 'Create workspace root')) { New-Item -ItemType Directory -Force -Path $Root | Out-Null } -$results = foreach ($repo in $repositories) { +$results = foreach ($repo in $contextRepositories) { $path = Join-Path $Root $repo.RelativePath if ($repo.Kind -eq 'memory') { $memoryGitEntry = Join-Path $path '.git' diff --git a/tests/Initialize-MsxWorkspace.Tests.ps1 b/tests/Initialize-MsxWorkspace.Tests.ps1 index 13f546b..e4b9f0a 100644 --- a/tests/Initialize-MsxWorkspace.Tests.ps1 +++ b/tests/Initialize-MsxWorkspace.Tests.ps1 @@ -103,15 +103,11 @@ Describe 'Initialize-MsxWorkspace context freshness' { $docsRemote = $Fixture.Remotes.docs.Replace("'", "''") $memoryRemote = $Fixture.Remotes.memory.Replace("'", "''") @" -`$projects = @( - @{ - Name = 'Fixture' - Path = '' - DocsUrl = '$docsRemote' - MemoryUrl = '$memoryRemote' - } +`$repositories = @( + @{ Name = 'Fixture/docs'; Path = 'docs'; Url = '$docsRemote'; Kind = 'docs' } + @{ Name = 'Fixture/memory'; Path = 'memory'; Url = '$memoryRemote'; Kind = 'memory' } ) -& '$bootstrap' -Root '$workspace' -Project `$projects -UserName 'Fixture User' -UserEmail 'fixture@example.invalid' +& '$bootstrap' -Root '$workspace' -Repository `$repositories -UserName 'Fixture User' -UserEmail 'fixture@example.invalid' exit `$LASTEXITCODE "@ | Set-Content -LiteralPath $runner $output = & $script:pwsh -NoProfile -File $runner 2>&1 | Out-String @@ -349,41 +345,33 @@ exit `$LASTEXITCODE Should -BeExactly $memoryBefore } - It 'installs additional project context through plug-in coordinates' { + It 'installs additional context through explicit repository coordinates' { $runner = Join-Path $fixture.Root 'invoke-project-bootstrap.ps1' $bootstrap = $script:bootstrap.Replace("'", "''") $workspace = $fixture.Workspace.Replace("'", "''") $docsRemote = $fixture.Remotes.docs.Replace("'", "''") $memoryRemote = $fixture.Remotes.memory.Replace("'", "''") @" -`$projects = @( - @{ - Name = 'MSXOrg' - Path = '' - DocsUrl = '$docsRemote' - MemoryUrl = '$memoryRemote' - } - @{ - Name = 'Project' - Path = './projects/Project/' - DocsUrl = '$docsRemote' - MemoryUrl = '$memoryRemote' - } +`$repositories = @( + @{ Name = 'MSXOrg/docs'; Path = 'docs'; Url = '$docsRemote'; Kind = 'docs' } + @{ Name = 'MSXOrg/memory'; Path = 'memory'; Url = '$memoryRemote'; Kind = 'memory' } + @{ Name = 'Project/process'; Path = './projects/Project/process/'; Url = '$docsRemote'; Kind = 'docs' } + @{ Name = 'Project/memory'; Path = './projects/Project/memory/'; Url = '$memoryRemote'; Kind = 'memory' } ) -& '$bootstrap' -Root '$workspace' -Project `$projects -UserName 'Fixture User' -UserEmail 'fixture@example.invalid' +& '$bootstrap' -Root '$workspace' -Repository `$repositories -UserName 'Fixture User' -UserEmail 'fixture@example.invalid' exit `$LASTEXITCODE "@ | Set-Content -LiteralPath $runner $output = & $script:pwsh -NoProfile -File $runner 2>&1 | Out-String $LASTEXITCODE | Should -Be 0 -Because $output - $projectDocs = Join-Path $fixture.Workspace 'projects/Project/docs' + $projectDocs = Join-Path $fixture.Workspace 'projects/Project/process' $projectMemory = Join-Path $fixture.Workspace 'projects/Project/memory' Test-Path -LiteralPath (Join-Path $projectDocs '.git') | Should -BeTrue Test-Path -LiteralPath (Join-Path $projectMemory '.git') | Should -BeTrue - Test-Path -LiteralPath (Join-Path $fixture.Workspace 'projects/Project/docs.git') | Should -BeTrue + Test-Path -LiteralPath (Join-Path $fixture.Workspace 'projects/Project/process.git') | Should -BeTrue (Invoke-Git -Arguments @( - "--git-dir=$(Join-Path $fixture.Workspace 'projects/Project/docs.git')", + "--git-dir=$(Join-Path $fixture.Workspace 'projects/Project/process.git')", 'rev-parse', '--is-bare-repository' )).Trim() | Should -BeExactly 'true' @@ -400,28 +388,18 @@ exit `$LASTEXITCODE $docsRemote = $fixture.Remotes.docs.Replace("'", "''") $memoryRemote = $fixture.Remotes.memory.Replace("'", "''") @" -`$projects = @( - @{ - Name = 'One' - Path = '' - DocsUrl = '$docsRemote' - MemoryUrl = '$memoryRemote' - } - @{ - Name = 'Two' - Path = '.' - DocsUrl = '$docsRemote' - MemoryUrl = '$memoryRemote' - } +`$repositories = @( + @{ Name = 'One/docs'; Path = 'same'; Url = '$docsRemote'; Kind = 'docs' } + @{ Name = 'Two/memory'; Path = './same/'; Url = '$memoryRemote'; Kind = 'memory' } ) -& '$bootstrap' -Root '$workspace' -Project `$projects -UserName 'Fixture User' -UserEmail 'fixture@example.invalid' +& '$bootstrap' -Root '$workspace' -Repository `$repositories -UserName 'Fixture User' -UserEmail 'fixture@example.invalid' exit `$LASTEXITCODE "@ | Set-Content -LiteralPath $runner $output = & $script:pwsh -NoProfile -File $runner 2>&1 | Out-String $LASTEXITCODE | Should -Not -Be 0 - $output | Should -Match 'workspace paths overlap' + $output | Should -Match 'Repository paths overlap' } It 'rejects duplicate project names before mutation' -ForEach @( @@ -436,21 +414,11 @@ exit `$LASTEXITCODE $docsRemote = $fixture.Remotes.docs.Replace("'", "''") $memoryRemote = $fixture.Remotes.memory.Replace("'", "''") @" -`$projects = @( - @{ - Name = 'Duplicate' - Path = '' - DocsUrl = '$docsRemote' - MemoryUrl = '$memoryRemote' - } - @{ - Name = 'Duplicate' - Path = '$SecondPath' - DocsUrl = '$docsRemote' - MemoryUrl = '$memoryRemote' - } +`$repositories = @( + @{ Name = 'Duplicate'; Path = 'docs'; Url = '$docsRemote'; Kind = 'docs' } + @{ Name = 'Duplicate'; Path = '$SecondPath'; Url = '$memoryRemote'; Kind = 'memory' } ) -& '$bootstrap' -Root '$workspace' -Project `$projects -UserName 'Fixture User' -UserEmail 'fixture@example.invalid' +& '$bootstrap' -Root '$workspace' -Repository `$repositories -UserName 'Fixture User' -UserEmail 'fixture@example.invalid' exit `$LASTEXITCODE "@ | Set-Content -LiteralPath $runner @@ -488,28 +456,20 @@ exit `$LASTEXITCODE $docsRemote = $fixture.Remotes.docs.Replace("'", "''") $memoryRemote = $fixture.Remotes.memory.Replace("'", "''") @" -`$projects = @( - @{ - Name = 'MSXOrg' - Path = '' - DocsUrl = '$docsRemote' - MemoryUrl = '$memoryRemote' - } - @{ - Name = 'Unsafe' - Path = '$UnsafePath' - DocsUrl = '$docsRemote' - MemoryUrl = '$memoryRemote' - } +`$repositories = @( + @{ Name = 'MSXOrg/docs'; Path = 'docs'; Url = '$docsRemote'; Kind = 'docs' } + @{ Name = 'MSXOrg/memory'; Path = 'memory'; Url = '$memoryRemote'; Kind = 'memory' } + @{ Name = 'Unsafe/docs'; Path = '$UnsafePath/docs'; Url = '$docsRemote'; Kind = 'docs' } + @{ Name = 'Unsafe/memory'; Path = '$UnsafePath/memory'; Url = '$memoryRemote'; Kind = 'memory' } ) -& '$bootstrap' -Root '$workspace' -Project `$projects -UserName 'Fixture User' -UserEmail 'fixture@example.invalid' +& '$bootstrap' -Root '$workspace' -Repository `$repositories -UserName 'Fixture User' -UserEmail 'fixture@example.invalid' exit `$LASTEXITCODE "@ | Set-Content -LiteralPath $runner $output = & $script:pwsh -NoProfile -File $runner 2>&1 | Out-String $LASTEXITCODE | Should -Not -Be 0 - $output | Should -Match 'workspace paths overlap' + $output | Should -Match 'Repository paths overlap' $unsafeRoot = Join-Path $fixture.Workspace $UnsafePath foreach ($child in @('docs', 'docs.git', 'memory', 'docs.simple-clone-backup')) { Test-Path -LiteralPath (Join-Path $unsafeRoot $child) | Should -BeFalse @@ -531,28 +491,18 @@ exit `$LASTEXITCODE $docsRemote = $fixture.Remotes.docs.Replace("'", "''") $memoryRemote = $fixture.Remotes.memory.Replace("'", "''") @" -`$projects = @( - @{ - Name = 'Parent' - Path = 'projects/Parent' - DocsUrl = '$docsRemote' - MemoryUrl = '$memoryRemote' - } - @{ - Name = 'Child' - Path = 'projects/Parent/Child' - DocsUrl = '$docsRemote' - MemoryUrl = '$memoryRemote' - } +`$repositories = @( + @{ Name = 'Parent'; Path = 'projects/Parent'; Url = '$docsRemote'; Kind = 'docs' } + @{ Name = 'Child'; Path = 'projects/Parent/Child'; Url = '$memoryRemote'; Kind = 'memory' } ) -& '$bootstrap' -Root '$workspace' -Project `$projects -UserName 'Fixture User' -UserEmail 'fixture@example.invalid' +& '$bootstrap' -Root '$workspace' -Repository `$repositories -UserName 'Fixture User' -UserEmail 'fixture@example.invalid' exit `$LASTEXITCODE "@ | Set-Content -LiteralPath $runner $output = & $script:pwsh -NoProfile -File $runner 2>&1 | Out-String $LASTEXITCODE | Should -Not -Be 0 - $output | Should -Match 'workspace paths overlap' + $output | Should -Match 'Repository paths overlap' Test-Path -LiteralPath (Join-Path $fixture.Workspace 'projects') | Should -BeFalse } @@ -589,15 +539,11 @@ exit `$LASTEXITCODE $docsRemote = $fixture.Remotes.docs.Replace("'", "''") $memoryRemote = $fixture.Remotes.memory.Replace("'", "''") @" -`$projects = @( - @{ - Name = 'Fixture' - Path = '' - DocsUrl = '$docsRemote' - MemoryUrl = '$memoryRemote' - } +`$repositories = @( + @{ Name = 'Fixture/docs'; Path = 'docs'; Url = '$docsRemote'; Kind = 'docs' } + @{ Name = 'Fixture/memory'; Path = 'memory'; Url = '$memoryRemote'; Kind = 'memory' } ) -& '$bootstrap' -Root '$emptyRoot' -Project `$projects -UserName 'Fixture User' -UserEmail 'fixture@example.invalid' +& '$bootstrap' -Root '$emptyRoot' -Repository `$repositories -UserName 'Fixture User' -UserEmail 'fixture@example.invalid' exit `$LASTEXITCODE "@ | Set-Content -LiteralPath $runner @@ -653,15 +599,11 @@ exit `$LASTEXITCODE $docsRemote = $fixture.Remotes.docs.Replace("'", "''") $memoryRemote = $fixture.Remotes.memory.Replace("'", "''") @" -`$projects = @( - @{ - Name = 'Fixture' - Path = '' - DocsUrl = '$docsRemote' - MemoryUrl = '$memoryRemote' - } +`$repositories = @( + @{ Name = 'Fixture/docs'; Path = 'docs'; Url = '$docsRemote'; Kind = 'docs' } + @{ Name = 'Fixture/memory'; Path = 'memory'; Url = '$memoryRemote'; Kind = 'memory' } ) -& '$bootstrap' -Root '$emptyRoot' -Project `$projects -UserName 'Fixture User' -UserEmail 'fixture@example.invalid' +& '$bootstrap' -Root '$emptyRoot' -Repository `$repositories -UserName 'Fixture User' -UserEmail 'fixture@example.invalid' exit `$LASTEXITCODE "@ | Set-Content -LiteralPath $runner @@ -682,15 +624,11 @@ exit `$LASTEXITCODE $memoryRemote = $fixture.Remotes.memory.Replace("'", "''") @" `$env:MSX_BOOTSTRAP_TEST_FAIL_AFTER_DOCS_MOVE = '1' -`$projects = @( - @{ - Name = 'Fixture' - Path = '' - DocsUrl = '$docsRemote' - MemoryUrl = '$memoryRemote' - } +`$repositories = @( + @{ Name = 'Fixture/docs'; Path = 'docs'; Url = '$docsRemote'; Kind = 'docs' } + @{ Name = 'Fixture/memory'; Path = 'memory'; Url = '$memoryRemote'; Kind = 'memory' } ) -& '$bootstrap' -Root '$workspace' -Project `$projects -UserName 'Fixture User' -UserEmail 'fixture@example.invalid' +& '$bootstrap' -Root '$workspace' -Repository `$repositories -UserName 'Fixture User' -UserEmail 'fixture@example.invalid' exit `$LASTEXITCODE "@ | Set-Content -LiteralPath $runner @@ -713,15 +651,11 @@ exit `$LASTEXITCODE $memoryRemote = $fixture.Remotes.memory.Replace("'", "''") @" `$env:MSX_BOOTSTRAP_TEST_FAIL_DOCS_MOVE = '1' -`$projects = @( - @{ - Name = 'Fixture' - Path = '' - DocsUrl = '$docsRemote' - MemoryUrl = '$memoryRemote' - } +`$repositories = @( + @{ Name = 'Fixture/docs'; Path = 'docs'; Url = '$docsRemote'; Kind = 'docs' } + @{ Name = 'Fixture/memory'; Path = 'memory'; Url = '$memoryRemote'; Kind = 'memory' } ) -& '$bootstrap' -Root '$workspace' -Project `$projects -UserName 'Fixture User' -UserEmail 'fixture@example.invalid' +& '$bootstrap' -Root '$workspace' -Repository `$repositories -UserName 'Fixture User' -UserEmail 'fixture@example.invalid' exit `$LASTEXITCODE "@ | Set-Content -LiteralPath $runner @@ -814,7 +748,7 @@ exit `$LASTEXITCODE $bootstrapText | Should -Match ([regex]::Escape("Path = '$($repository.Path)'")) $bootstrapText | Should -Match ([regex]::Escape("Url = '$($repository.Url)'")) } - $bootstrapText | Should -Not -Match 'PSModule/docs' + $bootstrapText | Should -Not -Match 'github\.com/PSModule/docs' $bootstrapText | Should -Not -Match "Join-Path `$HOME '\.msx'" } From 2ee22c77e6cd758e55d94f4b1bb44e0aee6aa4c8 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 29 Aug 2026 13:06:53 +0200 Subject: [PATCH 03/19] Align agent context with source repositories --- .../SKILL.md | 2 +- .../agentic-development/conformance.md | 4 +- .../agentic-development/design.md | 120 +++++++++++------- .../agentic-development/memory-template.md | 4 +- .../Capabilities/agentic-development/spec.md | 34 ++--- src/docs/Initiatives/PSModule.md | 2 +- src/docs/Ways-of-Working/Git-Worktrees.md | 2 +- .../Ways-of-Working/Repository-Standard.md | 2 +- 8 files changed, 103 insertions(+), 67 deletions(-) diff --git a/.github/plugin/msx/skills/msx-ways-of-working-agentic-development/SKILL.md b/.github/plugin/msx/skills/msx-ways-of-working-agentic-development/SKILL.md index 2682252..4986e95 100644 --- a/.github/plugin/msx/skills/msx-ways-of-working-agentic-development/SKILL.md +++ b/.github/plugin/msx/skills/msx-ways-of-working-agentic-development/SKILL.md @@ -5,4 +5,4 @@ description: Apply the MSX agentic development way of working. # Follow MSX agentic development -Read and follow [MSX Agentic Development](https://github.com/MSXOrg/docs/blob/main/src/docs/Ways-of-Working/Agentic-Development.md). +Read and follow [MSX Agentic Development](https://github.com/MSXOrg/docs/blob/main/src/docs/Capabilities/agentic-development/index.md). diff --git a/src/docs/Capabilities/agentic-development/conformance.md b/src/docs/Capabilities/agentic-development/conformance.md index f0ce149..881f7cc 100644 --- a/src/docs/Capabilities/agentic-development/conformance.md +++ b/src/docs/Capabilities/agentic-development/conformance.md @@ -22,8 +22,8 @@ A conformant repository MUST provide all of the following. | **A router agent file** | The repository root holds a single agent instruction file, and it routes rather than instructs ([design](design.md#pointer-files)) | | **Reading order** | The router states the order in which context is read, from repository-local to organization-canonical | | **Client routes** | Every supported runtime's expected instruction path exists and resolves to the router, carrying no content of its own ([client behavior](design.md#client-behavior)) | -| **Canonical coordinates** | The router names the organization's canonical documentation and memory locations, so context is reachable without prior knowledge | -| **Freshness** | Canonical context is refreshed at the start of every session, in every runtime ([refresh hooks](design.md#refresh-hooks)) | +| **Canonical coordinates** | The router names each source repository, entry file, published documentation when available, private memory status, and preferred local clone | +| **Freshness** | The router requires the newest source version, and every local clone is refreshed before use ([refresh hooks](design.md#refresh-hooks)) | | **Precedence** | The router states that local files never override a standard and that memory never overrides documentation | The baseline is small on purpose. Every item is something an agent needs before it can find diff --git a/src/docs/Capabilities/agentic-development/design.md b/src/docs/Capabilities/agentic-development/design.md index 618faa5..d04155e 100644 --- a/src/docs/Capabilities/agentic-development/design.md +++ b/src/docs/Capabilities/agentic-development/design.md @@ -5,7 +5,7 @@ description: How the agentic development framework is built — OKF documentatio # Agentic Development — Design -The behavior in the [spec](spec.md) is delivered by an organization-level documentation and memory pair, adopted by each product repository through thin pointer files. The design keeps project knowledge in one reviewed place, keeps working memory in one durable place, and lets each agent runtime adapt without copying process knowledge. +The behavior in the [spec](spec.md) is delivered by an organization-level documentation and memory source pair, adopted by each product repository through thin pointer files. The design keeps project knowledge in one reviewed place, keeps working memory in one durable place, and lets each agent runtime adapt without copying process knowledge. ## Organization anatomy @@ -13,27 +13,27 @@ The GitHub organization is the project boundary. The host distinguishes work fro ```text // - docs/ # canonical knowledge base; changes through pull requests - memory/ # durable agent and team memory; versioned working knowledge - / # product or component repository + / # canonical knowledge base; changes through pull requests + memory/ # durable agent and team memory; versioned working knowledge + / # product or component repository / ``` -Current project scopes follow the same shape: +Current project scopes identify these concrete sources: -| Host | Organization | Docs | Memory | -| --- | --- | --- | --- | -| `github.com` | `MSXOrg` | `MSXOrg/docs` | `MSXOrg/memory` | -| `github.com` | `PSModule` | `PSModule/docs` | `PSModule/memory` | -| `` | `` | `/docs` | `/memory` | +| Host | Organization | Documentation source | Preferred clone | Memory source | Preferred clone | +| --- | --- | --- | --- | --- | --- | +| `github.com` | `MSXOrg` | `MSXOrg/docs` | `~/.msxorg/docs` | Private `MSXOrg/memory` | `~/.msxorg/memory` | +| `github.com` | `PSModule` | `PSModule/Process-PSModule` | `~/.psmodule/process-psmodule` | Private `PSModule/memory` | `~/.psmodule/memory` | +| `` | `` | Designated `/` | Declared by the router | Private `/memory` | Declared by the router | -The last row is the general case: any adopting organization on any GitHub host — public or an enterprise instance — plugs into the same shape without changing the framework. +The last row is the general case: any adopting organization on any GitHub host — public or an enterprise instance — plugs into the same shape without changing the framework. Repository identity remains stable whether an agent reads with a CLI, through the web, from published documentation, or from a refreshed local clone. ## Repository roles -### `docs` +### Documentation source -The `docs` repository is the canonical knowledge base. It owns: +The designated documentation repository is the canonical knowledge base. It owns: - vision, principles, and ways of working; - coding standards and documentation standards; @@ -41,11 +41,11 @@ The `docs` repository is the canonical knowledge base. It owns: - project glossary and onboarding; - the canonical Workflow and its linked stage procedures. -Changes to `docs` happen through pull requests because this repository defines durable project intent. +Changes happen through pull requests because this repository defines durable project intent. `MSXOrg/docs` fills this role for MSXOrg. `PSModule/Process-PSModule` fills it for PSModule-specific process and standards while PSModule inherits cross-organization standards from `MSXOrg/docs`. ### `memory` -The `memory` repository is the durable working-memory store. It owns: +The private `memory` repository is the durable working-memory store. It owns: - recurring gotchas and lessons learned; - active project context that should survive a single chat session; @@ -141,7 +141,7 @@ flowchart TD host -->|"github.com/PSModule"| psmodule["PSModule context"] host -->|"any adopting org"| other["<host>/<org> context"] - msx --> refresh["Refresh selected docs + memory
stop unless exactly synchronized"] + msx --> refresh["Resolve newest selected sources
refresh local clones before use"] psmodule --> refresh other --> refresh refresh --> repo["Read README, CONTRIBUTING,
and local docs"] @@ -164,24 +164,56 @@ Resolution is deterministic. If the active repository remote is `github.com/PSMo ## Pointer files -`AGENTS.md` is the cross-runtime router. It names the project and lists where to read, in order. It holds nothing else — no bootstrap, no build commands, no contribution mechanics, no standards. +`AGENTS.md` is the cross-runtime router. It leads with the authority and freshness directive, names the repository, and lists where to read in order. Each canonical source identifies its repository, entry file, published documentation when available, private status, and preferred clone. It holds no bootstrap, build commands, contribution mechanics, or standards. ```markdown # Agent Instructions -This repository is `github.com/MSXOrg/`. Read in this order: +Read nearest first, prefer documentation over memory, and always use the newest version. + +This repository is `github.com/MSXOrg/`. Read these sources in order: 1. `README.md` — what this repository is and how it builds. 2. `CONTRIBUTING.md` — how a change is made and reviewed here. 3. `docs/index.md` — this repository's own documentation. -4. `~/.msx/docs/src/docs/index.md` — the organization standards. -5. `~/.msx/memory/index.md` — durable lessons, read last. +4. [MSXOrg/docs](https://github.com/MSXOrg/docs) — entry file `src/docs/index.md`; + published at ; preferred clone `~/.msxorg/docs`. +5. `MSXOrg/memory` — private; entry file `index.md`; preferred clone + `~/.msxorg/memory`; read last. + +Use a CLI, the web, published documentation, or a refreshed local clone, whichever +provides the newest accessible source. +``` -Read nearest first. A local file never overrides a standard, and memory never -overrides documentation. +A PSModule repository adds its organization sources and inherited MSX sources: + +```markdown +# Agent Instructions + +Read nearest first, prefer documentation over memory, and always use the newest version. + +This repository is `github.com/PSModule/`. Read these sources in order: + +1. `README.md` — what this repository is and how it builds. +2. `CONTRIBUTING.md` — how a change is made and reviewed here. +3. `docs/index.md` — this repository's own documentation, when present. +4. [PSModule/Process-PSModule](https://github.com/PSModule/Process-PSModule) — + entry file `docs/index.md`; published at + ; preferred clone + `~/.psmodule/process-psmodule`. +5. [MSXOrg/docs](https://github.com/MSXOrg/docs) — inherited standards; entry file + `src/docs/index.md`; published at ; preferred + clone `~/.msxorg/docs`. +6. `PSModule/memory` — private; entry file `index.md`; preferred clone + `~/.psmodule/memory`; read last. +7. `MSXOrg/memory` — private inherited memory; entry file `index.md`; preferred + clone `~/.msxorg/memory`; read last. + +Use a CLI, the web, published documentation, or a refreshed local clone, whichever +provides the newest accessible source. ``` -A router lists the destinations that exist in that repository, written as the paths that repository actually uses — the ones above are an example, not a required layout. A repository with no documentation of its own drops that line; one that publishes the standards resolves steps 3 and 4 to the same tree and drops the duplicate. Writing a real path matters more than matching the example, because the router is read literally. +A router lists only destinations that apply to its repository. A repository with no documentation of its own drops that line; one that publishes the organization standards resolves local and organization documentation to the same source and drops the duplicate. The route does not require a particular client or access method. A local clone is usable only after the freshness gate succeeds. The index trail is the default. A clear prompt can shortcut stage discovery: `Review this PR ` enters Review, `Make this issue ` enters Define, and `Implement ` enters Implement. These phrases are routing hints interpreted by [Workflow](../../Ways-of-Working/Workflow.md#find-the-current-stage), not commands with independent procedures. @@ -210,28 +242,29 @@ Path-scoped instruction files are reserved for local rules that cannot live cent A local bootstrap makes central context predictable: ```text -~/.msx/ - docs.git/ # MSXOrg/docs bare backing repository - docs/ # clean MSXOrg/docs main worktree - memory/ # simple MSXOrg/memory checkout - projects/ - PSModule/ - docs.git/ # optional project docs backing repository - docs/ # optional project docs main worktree - memory/ # optional project memory checkout +~/ + .msxorg/ + docs.git/ # MSXOrg/docs bare backing repository + docs/ # clean MSXOrg/docs default-branch worktree + memory/ # private MSXOrg/memory simple checkout + .psmodule/ + process-psmodule.git/ # PSModule/Process-PSModule bare backing repository + process-psmodule/ # clean Process-PSModule default-branch worktree + memory/ # private PSModule/memory simple checkout ``` -The bootstrap clones missing repositories and fetches every existing context repository before use. Each clone must be clean, checked out on the remote default branch, and exactly equal to the fetched remote head. A dirty, locally ahead, diverged, wrong-branch, or unreachable clone stops context resolution; the agent does not use a possibly stale local copy. Bootstrap writes repository-local git configuration only. +The bootstrap takes repository identity, transport URL, kind, and preferred relative path as explicit configuration. It clones missing repositories and fetches every existing local context repository before use. Each clone must be clean, checked out on the remote default branch, and exactly equal to the fetched remote head. A dirty, locally ahead, diverged, wrong-branch, noncanonical, or unreachable clone stops local resolution; the agent does not use a possibly stale local copy. An agent may instead resolve the named source through a current remote CLI, web, or published-documentation route. Bootstrap writes repository-local git configuration only. -MSXOrg is the default project. Additional projects plug in a name, relative workspace path, docs URL, and memory URL. For example, PSModule can use `projects/PSModule/{docs,memory}` beneath the same workspace while reusing the identical synchronization and validation path. Repository agent files retain this small coordinate block because it is required before project documentation can be reached; the reusable bootstrap behavior remains central. +The former `~/.msx/` tree is not a fallback. Recognized former paths produce explicit diagnostics, remain unchanged for manual verification, and are replaced by fresh canonical clones at the organization-addressable paths. Existing simple documentation clones already at canonical paths are converted only after synchronization and are retained as backups. This separates safe migration from stale-context acceptance. ## Refresh hooks -The freshness gate is only worth as much as the last time it ran. A workspace bootstrapped +The local freshness gate is only worth as much as the last time it ran. A workspace bootstrapped once is current at that moment and progressively less so afterwards, and an agent reading a -week-old clone reads a standard that has since changed while believing it is canonical. +week-old clone reads a standard that has since changed while believing it is canonical. A runtime +that reads through a current remote CLI, web, or published route does not need a local refresh. -So the refresh runs at the **start of every session**, not once per machine. What differs +When preferred clones are used, refresh runs at the **start of every session**, not once per machine. What differs between runtimes is where the trigger hangs, never what it does: | Runtime shape | Lifecycle point | How the refresh attaches | @@ -251,10 +284,10 @@ The refresh MUST be idempotent, because it runs far more often than it changes a hook that is expensive or noisy when everything is already current gets disabled, and a disabled hook is worse than no hook, because the workspace still looks bootstrapped. -Where a runtime offers no lifecycle point at all, the refresh MUST be invoked explicitly -before context is read. It MUST NOT be skipped on the grounds that the workspace was -bootstrapped recently; "recently" is not a state the agent can observe, and the gate exists -precisely to replace that judgement with a check. +Where a runtime uses local clones but offers no lifecycle point, the refresh MUST be invoked +explicitly before context is read. It MUST NOT be skipped on the grounds that the workspace +was bootstrapped recently; "recently" is not a state the agent can observe, and the gate +exists precisely to replace that judgment with a check. Each shape's obligations beyond the refresh — its entry file, tool declaration, and identity — are set out in [Runtime Integration](runtime-integration.md). @@ -296,7 +329,8 @@ Because Copilot code review reads the head branch, a pull request that changes ` | Failure | Design response | | --- | --- | | Repository does not identify its organization context | Infer from remote URL; ask when ambiguous. | -| A docs or memory clone is missing or cannot synchronize | Bootstrap or repair it, then retry. Stop context resolution until every canonical context repository passes the freshness gate. | +| A documentation or memory clone is missing or cannot synchronize | Use a current remote route, or bootstrap or repair the preferred clone before reading it. Never use the stale clone as fallback. | +| A former `~/.msx/` path exists | Diagnose it, ignore it as context, and create or refresh the canonical organization-addressable clone. Retain the former path until a human verifies removal. | | Pointer file duplicates central standards | Replace duplicated content with a route during review. A client file holds a pointer, not a copy. | | A skill, command, named agent, or instruction file defines a workflow stage | Delete the duplicate procedure and link to Workflow or its stage page. | | Memory conflicts with docs | Docs win; memory is corrected or removed. | @@ -306,7 +340,7 @@ Because Copilot code review reads the head branch, a pull request that changes ` ## Adoption path -1. Create or identify the organization `docs` repository. +1. Create or identify the organization's canonical documentation source repository. 2. Create or identify the organization `memory` repository, using the [Memory Repository Template](memory-template.md) as the starting scaffold. 3. Add `docs/index.md` and `memory/index.md` as the two root maps. 4. Add the canonical Workflow and linked stage procedures to `docs`. diff --git a/src/docs/Capabilities/agentic-development/memory-template.md b/src/docs/Capabilities/agentic-development/memory-template.md index e96a733..736aff5 100644 --- a/src/docs/Capabilities/agentic-development/memory-template.md +++ b/src/docs/Capabilities/agentic-development/memory-template.md @@ -5,8 +5,8 @@ description: The concrete, copy-pasteable scaffold every organization's memory r # Memory Repository Template -[Spec](spec.md) and [Design](design.md) require every adopting organization to have a -`memory` repository, and the design's [organization anatomy](design.md#organization-anatomy) +[Spec](spec.md) and [Design](design.md) require every adopting organization to identify a +`memory` source repository, and the design's [organization anatomy](design.md#organization-anatomy) already names `MSXOrg/memory` and `PSModule/memory` as canonical examples. Neither design document defines an exact file layout — this page is that layout. It is the one scaffold every adopting organization's `memory` repository instantiates. Content differs per diff --git a/src/docs/Capabilities/agentic-development/spec.md b/src/docs/Capabilities/agentic-development/spec.md index 87bb2e5..7afb4d6 100644 --- a/src/docs/Capabilities/agentic-development/spec.md +++ b/src/docs/Capabilities/agentic-development/spec.md @@ -9,10 +9,10 @@ description: Requirements for refresh-first, index-first agentic development thr An agent does useful work only when it knows which project it is serving, which standards apply, and what the team has already learned. That context MUST be project-scoped, durable, reviewable, and readable by humans and agents alike. The project boundary is the GitHub organization — `github.com/MSXOrg`, `github.com/PSModule`, and any other organization that adopts the framework, on any GitHub host. -Each organization owns two canonical repositories: +Each organization identifies canonical documentation and memory source repositories: -- `docs` — the reviewed knowledge base: vision, standards, workflows, specs, designs, glossary, onboarding, and project-wide rules. -- `memory` — the durable agent working memory: lessons learned, recurring gotchas, active context, workflow-stage knowledge, and project-specific operating notes. +- A documentation source — the reviewed knowledge base: vision, standards, workflows, specs, designs, glossary, onboarding, and project-wide rules. The repository is commonly named `docs`, but an organization MAY designate a repository such as `PSModule/Process-PSModule` when that repository owns its process and standards. +- A `memory` source — the durable agent working memory: lessons learned, recurring gotchas, active context, workflow-stage knowledge, and project-specific operating notes. Product repositories do not copy that knowledge. They carry thin pointer files that identify the organization context and direct agents to the relevant `docs` and `memory` roots before acting. @@ -31,7 +31,7 @@ Applies to any organization that wants a shared project knowledge base and memor **In scope** -- Organization-level `docs` and `memory` repositories. +- Organization-level documentation and memory source repositories. - Markdown documents with YAML frontmatter, following the [Open Knowledge Format](../../Dictionary/index.md#open-knowledge-format) model. - Thin repository pointer files: a required `AGENTS.md` router, and a route to it for every client that cannot read it. - Path-scoped rule files, reserved for local caveats that cannot live in repository or central documentation. @@ -54,23 +54,25 @@ Applies to any organization that wants a shared project knowledge base and memor ## Requirements - **Organization is the project boundary.** The framework MUST resolve project context from the Git host and organization before resolving repository-specific context. -- **Canonical docs repository.** Each adopting organization MUST have a `docs` repository that owns the reviewed knowledge base. +- **Canonical documentation repository.** Each adopting organization MUST identify a repository that owns its reviewed knowledge base. - **Canonical memory repository.** Each adopting organization MUST have a `memory` repository that owns durable project memory and agent working knowledge. -- **Pluggable project context.** The bootstrap MUST accept project-specific docs and memory coordinates and collision-free relative workspace paths without requiring a fork of its synchronization logic. +- **Repository identity is authoritative.** Routers and bootstrap configuration MUST name each source as `/`. CLI, web, published-site, and refreshed-local-clone access are interchangeable delivery methods and MUST NOT redefine the source identity. +- **Pluggable project context.** The bootstrap MUST accept repository identities, transport URLs, kinds, and collision-free relative workspace paths without requiring a fork of its synchronization logic. - **OKF-style documents.** Knowledge and memory documents MUST be Markdown files with YAML frontmatter, one primary concept per page, and stable paths that act as identity. - **Small pages and indexes.** Documentation and memory SHOULD prefer small pages, each folder SHOULD have an `index.md`, and indexes MUST let a human or agent navigate inward from the root. -- **Thin pointer files.** Product repositories MUST carry an `AGENTS.md` at the repository root that routes an agent from the repository's own files outward to the organization documentation, any inherited ecosystem documentation, and memory. It MUST be limited to that route list and the repository's own coordinates. It MUST NOT duplicate standards, workflow stages, or reusable process knowledge, and MUST NOT carry build commands, contribution mechanics, or workspace bootstrap steps, each of which has an owning file of its own. -- **Refresh-first, index-first workflow discovery.** After every canonical context repository passes the freshness gate, a human or agent MUST be able to follow the docs root index to Ways of Working, the canonical Workflow, and the procedure for the current stage. +- **Thin pointer files.** Product repositories MUST carry an `AGENTS.md` at the repository root that routes an agent from the repository's own files outward to the organization documentation, any inherited ecosystem documentation, and memory. It MUST lead with `Read nearest first, prefer documentation over memory, and always use the newest version.` and identify each source repository, entry file, published documentation when available, private memory status, and preferred local clone. It MUST allow CLI, web, published-site, or refreshed-local-clone access rather than requiring one method. It MUST NOT duplicate standards, workflow stages, or reusable process knowledge, and MUST NOT carry build commands, contribution mechanics, or workspace bootstrap steps, each of which has an owning file of its own. +- **Freshness-first, index-first workflow discovery.** After every canonical source is resolved to its newest accessible version, a human or agent MUST be able to follow the documentation entry index to the applicable workflow and the procedure for the current stage. - **Stage resolution from work.** Agents MUST infer the current stage from the prompt and current artifacts. Explicit task language MAY shortcut to the matching stage, but the shortcut MUST resolve to the canonical documentation. - **One process source.** Skills, commands, named agents, and tool-specific instruction files MUST NOT redefine Workflow stages. A client convenience MAY link to a stage procedure and add only runtime mechanics. - **Segmentation before loading.** An agent MUST segment work by host, organization, repository, path, and task before loading project standards or memory. The repository router MUST supply the coordinates that make this possible by naming its host and organization. The instruction to segment belongs to the user-global bootstrap, which runs before any repository file is read; a per-repository file MUST NOT restate it. - **Client routes.** A runtime that cannot read `AGENTS.md` under its own filename MUST be given a route file — `.claude/CLAUDE.md`, `.github/copilot-instructions.md`, or the equivalent path for that runtime. A route file MUST contain only a pointer to `AGENTS.md` plus, at most, genuinely runtime-specific configuration that cannot be expressed as documentation. It MUST NOT restate standards, describe workflow behavior, or repeat the reading order. Duplication is a property of content rather than of filenames: a route holds nothing that can drift, so the number of route files is unconstrained while their contents are strictly limited. [Client behavior](design.md#client-behavior) names the exact set an MSX repository carries; an adopting organization MAY carry a different set for the runtimes it uses. - **Reading order and authority order are distinct.** An agent MUST read nearest context first, in the order the repository router defines. Precedence on conflict MUST run the opposite way: repository-local files MAY add nuance and narrow exceptions but MUST NOT override an organization or inherited ecosystem standard unless that standard permits a local exception, and memory MUST NOT override documentation. -- **Deterministic context resolution.** Agents MUST resolve context in layers: system and client policy, user preferences, the repository router, the context-repository freshness gate, repository context, path-scoped repository rules, organization docs, any inherited ecosystem docs, organization memory, then current task context. -- **Local-first availability.** The docs and memory repositories SHOULD be available locally in a predictable workspace so agents can read them without relying on search or web access. -- **Fresh context before use.** Every canonical context repository MUST be fetched and exactly synchronized with its remote default branch before its contents are read. Dirty, locally ahead, diverged, wrong-branch, or unreachable repositories MUST stop context resolution rather than fall back to stale content. +- **Deterministic context resolution.** Agents MUST resolve context in layers: system and client policy, user preferences, the repository router, the source freshness gate, repository context, path-scoped repository rules, organization documentation, any inherited ecosystem documentation, organization memory, then current task context. +- **Predictable local availability.** Canonical sources SHOULD be available at organization-addressable paths. The preferred paths are `~/.msxorg/docs`, `~/.msxorg/memory`, `~/.psmodule/process-psmodule`, and `~/.psmodule/memory`. +- **Fresh context before use.** Agents MUST use the newest accessible source version. Remote CLI, web, and published documentation MAY satisfy this directly. A local clone MUST be fetched and exactly synchronized with its remote default branch before its contents are read. Dirty, locally ahead, diverged, wrong-branch, or unreachable local clones MUST stop local context resolution rather than fall back to stale content. +- **Former layouts are never implicit fallbacks.** Bootstrap MUST diagnose recognized context under the former `~/.msx/` layout and MUST NOT read it as canonical context. Migration MUST create or refresh the canonical organization-addressable clone without destructively moving the former path; the former path remains available for manual verification and removal. - **Working checkouts are not context sources.** Canonical context MUST be read from the context repository clones that passed the freshness gate. A working checkout of a `docs` or `memory` repository — one cloned in order to change it rather than to be governed by it — MUST NOT be used as a context source, whatever path it occupies, because it sits outside the gate: nothing fetches it, and a superseded page in it is readable rather than missing, so the failure is silent. A reader MAY establish whether any checkout is current with `git rev-list --left-right --count HEAD...origin/` after fetching, which reports commits ahead and behind without changing the working tree. -- **Refresh once per session, not once per machine.** The freshness gate MUST run at the start of every agent session, in every runtime. A workspace that was synchronized at some earlier point MUST NOT be treated as current, because elapsed time is not a state the agent can observe. The refresh MUST be idempotent, so that running it when nothing has changed is cheap and silent; a refresh that is expensive or noisy at steady state gets bypassed, and a bypassed gate is worse than none because the workspace still appears synchronized. +- **Refresh local clones once per session, not once per machine.** When a runtime uses preferred local clones, the freshness gate MUST run at the start of every agent session. A workspace synchronized at an earlier point MUST NOT be treated as current, because elapsed time is not a state the agent can observe. The refresh MUST be idempotent, so running it when nothing has changed is cheap and silent. - **Memory is scoped by horizon.** Memory MUST separate entries that apply organization-wide, entries that apply to one repository, and notes that apply only to the task in hand. Session-scoped notes MUST NOT be shared: they MUST be excluded from the repository's history so that a scratchpad cannot be inherited as knowledge. Making a session note durable MUST be a deliberate act of promotion, which is where the entry is checked for whether it is actually true. - **Durable memory is committed as it is written.** A memory entry MUST be committed and pushed when it is written, one commit per discrete lesson, so that no remembered thing depends on a session ending cleanly. - **One tool layer, declared per runtime.** Where agents use external tools, the set of tool servers MUST be defined once as a logical layer and each runtime MUST declare that same set in its own native configuration format. A runtime MUST NOT define tools of its own that other runtimes lack, because a capability available in one client and absent in another makes the documented procedure conditional on which client is running it. @@ -83,7 +85,7 @@ Applies to any organization that wants a shared project knowledge base and memor ## Success criteria -- An agent working in `github.com/PSModule/` reads PSModule docs and memory, not another organization's rules. +- An agent working in `github.com/PSModule/` resolves `github.com/PSModule/Process-PSModule` and `github.com/PSModule/memory`, plus inherited `github.com/MSXOrg/docs` and `github.com/MSXOrg/memory`. - An agent working in `github.com/MSXOrg/` resolves `github.com/MSXOrg/docs` and `github.com/MSXOrg/memory` as the canonical project context. - An agent working in `//` for any adopting organization resolves `//docs` and `//memory` as the canonical project context, with no change to the framework. - A new product repository can adopt the framework by adding a router and the client routes that reach it, without copying standards or memory pages. @@ -91,7 +93,7 @@ Applies to any organization that wants a shared project knowledge base and memor - A human can start at `docs/index.md` or `memory/index.md` and navigate to the same context an agent uses. - A human or agent can follow `docs/index.md` → Ways of Working → Workflow → the current stage procedure without knowing a file path in advance. - A prompt such as `Review this PR ` reaches the Review procedure directly, while `Make this issue ` reaches Define, without a parallel process definition. -- A missing, dirty, locally ahead, diverged, wrong-branch, or unreachable canonical context repository stops discovery before any context index is read. +- A missing, dirty, locally ahead, diverged, wrong-branch, or unreachable preferred local clone stops local discovery before any context index is read; an agent may instead resolve the named source through another current access method. - A working checkout of a `docs` repository present on disk is not read as canonical context, and a reader can tell a current checkout from a stale one before trusting either. - Updating a standard in `docs` changes the canonical guidance without editing every repository. - Capturing a recurring lesson in `memory` makes it available to later agents working in the same organization. @@ -103,10 +105,10 @@ The framework uses this normative reading order: 1. **System and client policy** — non-project instructions imposed by the agent runtime. 2. **User-global preferences** — the human operator's baseline style and risk posture. 3. **Repository router** — `AGENTS.md` identifies the host, organization, and the context sources below, in the order they are read. -4. **Freshness gate** — fetch every canonical context repository and stop unless each clean default-branch checkout exactly matches its remote head. +4. **Freshness gate** — use the newest accessible source version; if using local clones, fetch each one and stop local resolution unless every clean default-branch checkout exactly matches its remote head. 5. **Repository context** — README, CONTRIBUTING, local docs, and narrow repository exceptions. 6. **Path-scoped repository rules** — local rules that apply to the files being read, generated, reviewed, or edited. -7. **Organization documentation** — the `docs` repository for the resolved organization: start at `docs/index.md`, traverse to Ways of Working and Workflow, resolve the current stage, then load the relevant standards, specs, and designs. +7. **Organization documentation** — the designated documentation source repository for the resolved organization: start at its declared entry file, traverse to the applicable workflow, then load the relevant standards, specs, and designs. 8. **Inherited ecosystem documentation** — where the organization inherits from a broader standard set, the layer it inherits from. 9. **Organization memory** — start at `memory/index.md`, then load relevant lessons, gotchas, and active context. 10. **Current task context** — issue, pull request, prompt, branch, diff, diagnostics, terminal output, and open files; use these artifacts to re-evaluate the stage after each handoff. diff --git a/src/docs/Initiatives/PSModule.md b/src/docs/Initiatives/PSModule.md index 1537f46..e712f58 100644 --- a/src/docs/Initiatives/PSModule.md +++ b/src/docs/Initiatives/PSModule.md @@ -22,4 +22,4 @@ Cross-org standards and reusable architecture are canonical in MSXOrg/docs, incl - [Capabilities](../Capabilities/index.md) - [PowerShell on GitHub capability](../Capabilities/powershell-on-github/index.md) -PSModule/docs is now intentionally scoped to module-specific operational details: module catalog pages, Process-PSModule repository anatomy, and template onboarding for module repositories. +`PSModule/Process-PSModule` is the canonical PSModule documentation source. It owns module-specific operational details, process and standards content, repository anatomy, and template onboarding. diff --git a/src/docs/Ways-of-Working/Git-Worktrees.md b/src/docs/Ways-of-Working/Git-Worktrees.md index 9321c05..6fdf059 100644 --- a/src/docs/Ways-of-Working/Git-Worktrees.md +++ b/src/docs/Ways-of-Working/Git-Worktrees.md @@ -42,7 +42,7 @@ In a single ordinary clone the opposite is forced: one branch checked out at a t - **`/`** — the canonical default-branch worktree. Kept clean and exactly synchronized for reading, diffing, and comparisons. Never directly committed to. - **`-/`** — one worktree folder per repository-delivery Task or Bug in flight, named by issue number and a short slug. The folder is a concise local path; its branch uses the required `/-` name, so the two names do not need to match. -For the central MSX context, this becomes `~/.msx/docs.git` plus the readable `~/.msx/docs` main worktree. Memory remains a simple checkout at `~/.msx/memory`. +For canonical context, the owning organization supplies the local root. MSXOrg uses `~/.msxorg/docs.git`, the readable `~/.msxorg/docs` default-branch worktree, and the simple `~/.msxorg/memory` checkout. PSModule uses `~/.psmodule/process-psmodule.git`, `~/.psmodule/process-psmodule`, and `~/.psmodule/memory`. ## Remotes diff --git a/src/docs/Ways-of-Working/Repository-Standard.md b/src/docs/Ways-of-Working/Repository-Standard.md index c8305a8..8fdc491 100644 --- a/src/docs/Ways-of-Working/Repository-Standard.md +++ b/src/docs/Ways-of-Working/Repository-Standard.md @@ -194,7 +194,7 @@ An initiative should document: - How the distributor or equivalent automation discovers repositories. - How exceptions are approved. -For example, PSModule can define its module-specific managed files in `PSModule/docs` and implement distribution in `PSModule/Distributor`. MSX only defines that such a standard and distribution path must exist. +For example, PSModule can define its module-specific managed files in `PSModule/Process-PSModule` and implement distribution in `PSModule/Distributor`. MSX only defines that such a standard and distribution path must exist. ## Where this connects From 34a41474e46a94025f9ac3a41ba5b4af2f1a7cf7 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 29 Aug 2026 13:06:58 +0200 Subject: [PATCH 04/19] Route agents through organization-owned context --- AGENTS.md | 10 +- CONTRIBUTING.md | 4 +- bootstrap/AGENTS.template.md | 150 ++++++++---------- bootstrap/README.md | 200 ++++++------------------ tests/Initialize-MsxWorkspace.Tests.ps1 | 49 +++--- 5 files changed, 158 insertions(+), 255 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 515f062..afc6944 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,12 +1,14 @@ # Agent Instructions -This repository is `github.com/MSXOrg/docs`. Read in this order: +Read nearest first, prefer documentation over memory, and always use the newest version. + +This repository is `github.com/MSXOrg/docs`. Read these sources in order: 1. [README.md](README.md) — what this repository is, how it is laid out, and how it builds. 2. [CONTRIBUTING.md](CONTRIBUTING.md) — how a change is made and reviewed here. -3. [src/docs/index.md](src/docs/index.md) — the documentation this repository owns. Follow the index inward. -4. `~/.msx/memory/index.md` — durable lessons from earlier work, read last. +3. [MSXOrg/docs](https://github.com/MSXOrg/docs) — this repository; entry file [src/docs/index.md](src/docs/index.md); published at ; preferred clone `~/.msxorg/docs`. +4. `MSXOrg/memory` — private organization memory; entry file `index.md`; preferred clone `~/.msxorg/memory`; read last. Step 3 is also the MSX organization standard, so nothing governs this repository from above it. -Read nearest first. A local file never overrides a standard, and memory never overrides documentation. +Use a CLI, the web, published documentation, or a refreshed local clone, whichever provides the newest accessible source. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4a65770..81da516 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -115,11 +115,11 @@ current state of the work. ## Agent workspace -Agents working here read organization memory from `~/.msx/memory`, set up by the +Agents working here read organization memory from `~/.msxorg/memory`, set up by the [workspace bootstrap](bootstrap/README.md). That bootstrap is user-global: it is installed once per machine, not per repository. -When a verified lesson is likely to matter again, record it in `~/.msx/memory` and push it +When a verified lesson is likely to matter again, record it in `~/.msxorg/memory` and push it directly to `main`, following that repository's own contribution guide. See the [README](README.md) for what this repository is and how it is laid out, and the diff --git a/bootstrap/AGENTS.template.md b/bootstrap/AGENTS.template.md index 97c923e..37b189e 100644 --- a/bootstrap/AGENTS.template.md +++ b/bootstrap/AGENTS.template.md @@ -1,28 +1,28 @@ # MSX workspace -The single starting point for any agent, in any repository. Before doing anything else, make sure the central workspace exists locally, then read from it. +Read nearest first, prefer documentation over memory, and always use the newest version. -## Main directive +Everything is a work in progress and can be improved. Fix a small problem when it is directly in scope; register a larger or unrelated problem as an issue in the repository that owns it. -Everything is a work in progress and can be updated and improved. Fix a small problem when it is directly in scope; register a larger or unrelated problem as an issue in the repository that owns it. +## First — refresh canonical context -## First — bootstrap the workspace - -The workspace is a git-isolated clone of the central repositories under `~/.msx`. Set it up before reading context. Existing context repositories must be clean, on their default branch, and exactly synchronized with the remote: +Canonical context is repository-addressable. An agent may use a CLI, the web, published documentation, or a refreshed local clone. The preferred local clones are refreshed at the start of every session so stale context is never accepted silently. ```powershell -$workspaceRoot = if ($env:MSX_WORKSPACE_ROOT) { $env:MSX_WORKSPACE_ROOT } else { Join-Path $HOME '.msx' } -$docsUrl = if ($env:MSX_DOCS_URL) { $env:MSX_DOCS_URL } else { 'https://github.com/MSXOrg/docs.git' } -$memoryUrl = if ($env:MSX_MEMORY_URL) { $env:MSX_MEMORY_URL } else { 'https://github.com/MSXOrg/memory.git' } -$docs = Join-Path $workspaceRoot 'docs' +$contextRoot = if ($env:MSX_CONTEXT_ROOT) { $env:MSX_CONTEXT_ROOT } else { $HOME } +$msxDocsUrl = if ($env:MSXORG_DOCS_URL) { $env:MSXORG_DOCS_URL } else { 'https://github.com/MSXOrg/docs.git' } +$msxMemoryUrl = if ($env:MSXORG_MEMORY_URL) { $env:MSXORG_MEMORY_URL } else { 'https://github.com/MSXOrg/memory.git' } +$psmoduleDocsUrl = if ($env:PSMODULE_DOCS_URL) { $env:PSMODULE_DOCS_URL } else { 'https://github.com/PSModule/Process-PSModule.git' } +$psmoduleMemoryUrl = if ($env:PSMODULE_MEMORY_URL) { $env:PSMODULE_MEMORY_URL } else { 'https://github.com/PSModule/memory.git' } +$docs = Join-Path $contextRoot '.msxorg/docs' $docsBacking = "$docs.git" -if ((Test-Path $docs) -and -not (Test-Path (Join-Path $docs '.git'))) { - throw "$docs exists but is not a git repository. Remove it and re-run." +if ((Test-Path -LiteralPath $docs) -and -not (Test-Path -LiteralPath (Join-Path $docs '.git'))) { + throw "$docs exists but is not a git repository. Reconcile it before using context." } -if (-not (Test-Path (Join-Path $docs '.git'))) { - if (-not (Test-Path $docsBacking)) { +if (-not (Test-Path -LiteralPath (Join-Path $docs '.git'))) { + if (-not (Test-Path -LiteralPath $docsBacking)) { New-Item -ItemType Directory -Force -Path (Split-Path -Parent $docs) | Out-Null - git clone --bare $docsUrl $docsBacking + git clone --bare $msxDocsUrl $docsBacking if ($LASTEXITCODE -ne 0) { throw "Bare clone of MSXOrg/docs failed (exit $LASTEXITCODE). Check network access and credentials." } @@ -30,23 +30,33 @@ if (-not (Test-Path (Join-Path $docs '.git'))) { if ((git --git-dir=$docsBacking rev-parse --is-bare-repository) -ne 'true') { throw "$docsBacking exists but is not a bare repository." } - if ((git --git-dir=$docsBacking remote get-url origin) -ne $docsUrl) { - throw "$docsBacking origin does not match canonical $docsUrl." + if ((git --git-dir=$docsBacking remote get-url origin) -ne $msxDocsUrl) { + throw "$docsBacking origin does not match canonical $msxDocsUrl." } $refspec = '+refs/heads/*:refs/remotes/origin/*' if ($refspec -notin @(git --git-dir=$docsBacking config --get-all remote.origin.fetch)) { git --git-dir=$docsBacking config --add remote.origin.fetch $refspec - if ($LASTEXITCODE -ne 0) { throw "Could not configure $docsBacking." } + if ($LASTEXITCODE -ne 0) { + throw "Could not configure $docsBacking." + } } git --git-dir=$docsBacking fetch origin --prune --quiet - if ($LASTEXITCODE -ne 0) { throw "Could not refresh $docsBacking. Do not use stale context." } + if ($LASTEXITCODE -ne 0) { + throw "Could not refresh $docsBacking. Do not use stale context." + } git --git-dir=$docsBacking remote set-head origin --auto | Out-Null - if ($LASTEXITCODE -ne 0) { throw "Could not detect the MSXOrg/docs default branch." } + if ($LASTEXITCODE -ne 0) { + throw 'Could not detect the MSXOrg/docs default branch.' + } $defaultRef = (git --git-dir=$docsBacking symbolic-ref --short refs/remotes/origin/HEAD | Out-String).Trim() - if ($LASTEXITCODE -ne 0) { throw "Could not resolve origin/HEAD in $docsBacking." } + if ($LASTEXITCODE -ne 0) { + throw "Could not resolve origin/HEAD in $docsBacking." + } $defaultBranch = $defaultRef -replace '^origin/', '' $remoteHead = (git --git-dir=$docsBacking rev-parse $defaultRef | Out-String).Trim() - if ($LASTEXITCODE -ne 0) { throw "Could not resolve $defaultRef in $docsBacking." } + if ($LASTEXITCODE -ne 0) { + throw "Could not resolve $defaultRef in $docsBacking." + } $localRef = "refs/heads/$defaultBranch" $localHead = (git --git-dir=$docsBacking rev-parse --verify $localRef 2>$null | Out-String).Trim() if ($LASTEXITCODE -eq 128) { @@ -55,7 +65,9 @@ if (-not (Test-Path (Join-Path $docs '.git'))) { throw "Could not inspect $localRef in $docsBacking." } elseif ($localHead -ne $remoteHead) { git --git-dir=$docsBacking merge-base --is-ancestor $localHead $remoteHead - if ($LASTEXITCODE -ne 0) { throw "$localRef is ahead or diverged in $docsBacking." } + if ($LASTEXITCODE -ne 0) { + throw "$localRef is ahead or diverged in $docsBacking." + } if ("branch $localRef" -in @(git --git-dir=$docsBacking worktree list --porcelain)) { throw "$localRef is checked out elsewhere. Update that worktree first." } @@ -69,8 +81,8 @@ if (-not (Test-Path (Join-Path $docs '.git'))) { throw "Could not create the canonical MSXOrg/docs worktree at $docs." } } else { - if ((git -C $docs remote get-url origin) -ne $docsUrl) { - throw "$docs origin does not match canonical $docsUrl." + if ((git -C $docs remote get-url origin) -ne $msxDocsUrl) { + throw "$docs origin does not match canonical $msxDocsUrl." } $refspec = '+refs/heads/*:refs/remotes/origin/*' if ($refspec -notin @(git -C $docs config --get-all remote.origin.fetch)) { @@ -84,9 +96,13 @@ if (-not (Test-Path (Join-Path $docs '.git'))) { throw "git fetch of MSXOrg/docs failed (exit $LASTEXITCODE). Do not use stale context." } git -C $docs remote set-head origin --auto | Out-Null - if ($LASTEXITCODE -ne 0) { throw "Could not detect the MSXOrg/docs default branch." } + if ($LASTEXITCODE -ne 0) { + throw 'Could not detect the MSXOrg/docs default branch.' + } $defaultRef = (git -C $docs symbolic-ref --short refs/remotes/origin/HEAD | Out-String).Trim() - if ($LASTEXITCODE -ne 0) { throw "Could not resolve origin/HEAD in $docs." } + if ($LASTEXITCODE -ne 0) { + throw "Could not resolve origin/HEAD in $docs." + } $defaultBranch = $defaultRef -replace '^origin/', '' $branch = (git -C $docs branch --show-current | Out-String).Trim() if ($branch -ne $defaultBranch) { @@ -103,73 +119,45 @@ if (-not (Test-Path (Join-Path $docs '.git'))) { throw "$docs is not exactly synchronized with $defaultRef. Reconcile local commits before using this context." } } -$projects = @( - @{ - Name = 'MSXOrg' - Path = '' - DocsUrl = $docsUrl - MemoryUrl = $memoryUrl - } - # Add project-specific entries when this template is adopted there: - # @{ - # Name = 'PSModule' - # Path = 'projects/PSModule' - # DocsUrl = 'https://github.com/PSModule/docs.git' - # MemoryUrl = 'https://github.com/PSModule/memory.git' - # } +$repositories = @( + @{ Name = 'MSXOrg/docs'; Path = '.msxorg/docs'; Url = $msxDocsUrl; Kind = 'docs' } + @{ Name = 'MSXOrg/memory'; Path = '.msxorg/memory'; Url = $msxMemoryUrl; Kind = 'memory' } + @{ Name = 'PSModule/Process-PSModule'; Path = '.psmodule/process-psmodule'; Url = $psmoduleDocsUrl; Kind = 'docs' } + @{ Name = 'PSModule/memory'; Path = '.psmodule/memory'; Url = $psmoduleMemoryUrl; Kind = 'memory' } ) -& (Join-Path $docs 'bootstrap/Initialize-MsxWorkspace.ps1') -Root $workspaceRoot -Project $projects +& (Join-Path $docs 'bootstrap/Initialize-MsxWorkspace.ps1') -Root $contextRoot -Repository $repositories if ($LASTEXITCODE -ne 0) { - throw "Context synchronization failed. Do not read context until every project is current." + throw 'Context synchronization failed. Do not read context until every repository is current.' } ``` -Keep the MSXOrg entry and add only the additional project coordinates required by repositories that inherit this template. Every project reuses the same synchronization and validation implementation. - -This produces: +The refresh creates: -- `~/.msx/docs.git` — bare backing repository for central docs. -- `~/.msx/docs` — clean, readable main worktree containing ways of working, standards, and workflow guidance. -- `~/.msx/memory` — what has been learned before: durable notes and prior session context. +- `~/.msxorg/docs` — `MSXOrg/docs`; entry file `src/docs/index.md`; published at . +- `~/.msxorg/memory` — private `MSXOrg/memory`; entry file `index.md`. +- `~/.psmodule/process-psmodule` — `PSModule/Process-PSModule`; entry file `docs/index.md`; published at . +- `~/.psmodule/memory` — private `PSModule/memory`; entry file `index.md`. -Each clone has repository-local git config only; it never modifies the global git config or the repository being worked in (git still reads them, but only repository-local config is written). +The corresponding `*.git` paths back the documentation worktrees. Memory remains a simple checkout. Repository-local git configuration is written only in these clones. -> `MSXOrg/memory` is private — the bootstrap needs access to it (and working github.com credentials) for the memory clone. +If the former `~/.msx/` layout exists, bootstrap reports every recognized path, ignores its contents, creates or refreshes the canonical organization-named clone, and retains the former path for manual verification and removal. Dirty or stale canonical clones stop context resolution. ## Then — read before acting -1. Segment the work by host, organization, repository, path, and task, so the right project context is selected before any of it is loaded. -2. Start at `~/.msx/docs/src/docs/index.md`. -3. Follow the Ways of Working index to `Workflow.md`. -4. Infer the current stage from the task and its artifacts, then read the linked stage procedure. -5. Read the relevant standards, repository context, and `~/.msx/memory`. +1. Segment the work by host, organization, repository, path, and task. +2. Read the selected repository's `AGENTS.md` route. +3. Follow repository context outward to the applicable documentation sources. +4. Resolve the current Workflow stage and read its canonical procedure. +5. Read relevant private memory last. -In a repository, its root `AGENTS.md` names the host and organization and lists the order to read in. This file carries the bootstrap and the segmentation step; the repository file carries the route. Neither restates the other. - -Clear task language may shortcut the index trail: `Review this PR ` enters Review, `Make this issue ` enters Define, and `Implement ` enters Implement. The linked documentation owns each procedure; this file does not define a separate agent or skill. - -## Interactions - -Some phrases operate on the session rather than on the work, and each one resolves to a procedure defined in the canonical Ways of Working: - -| Phrase | Means | -| --- | --- | -| `wrap up` | The session is ending — scan for untracked work and land each item in its proper artifact. | -| `park` | Move a tangent into an issue in the repository that owns it, then resume the original task. | -| `triage` | Classify and route an item without starting implementation. | -| `handoff` | Bring the artifacts to a state another participant can resume from. | - -Read `Ways-of-Working/Session-Interactions.md` in the canonical docs for what each one does. This table is a route, not a definition. +A repository router identifies source repositories and entry files. Use the newest accessible source through a CLI, the web, published documentation, or a refreshed preferred clone; no one delivery method is mandatory. ## Work in the selected repository -1. Read its `README.md` to understand the repository and its build. -2. Read its `CONTRIBUTING.md` for the contribution and review contract. -3. Use a dedicated worktree and the branch naming defined by the canonical Ways of Working. -4. Make small, descriptive micro-commits and push every commit so remote state, CI, and the draft pull request stay current. -5. Capture verified reusable lessons in organization memory, following that repository's own instructions. - -## Two write rules +1. Read its `README.md`. +2. Read its `CONTRIBUTING.md`. +3. Use a dedicated worktree and the canonical branch naming. +4. Make small descriptive commits and push each commit. +5. Capture verified reusable lessons in the applicable memory repository. -- **Docs change through topic worktrees and pull requests.** Create a topic worktree from `~/.msx/docs.git`; never branch or work inside the canonical `~/.msx/docs` main worktree. -- **Memory follows repository policy.** Read the selected memory repository's `AGENTS.md` and `CONTRIBUTING.md` before writing. +Documentation changes use topic worktrees created from the source repository's preferred bare clone, such as `~/.msxorg/docs.git` or `~/.psmodule/process-psmodule.git`. Memory follows its repository's own contribution policy. diff --git a/bootstrap/README.md b/bootstrap/README.md index 469d7a8..0142997 100644 --- a/bootstrap/README.md +++ b/bootstrap/README.md @@ -1,178 +1,80 @@ # Bootstrap -The single starting point for agents: a git-isolated local clone of the MSX central repositories under `~/.msx`, plus the instruction that sends every agent there first. +The bootstrap refreshes repository-addressable organization context before an agent reads it. Repository identity is authoritative; a CLI, the web, published documentation, or a refreshed local clone may deliver the content. ## Contents -- `Initialize-MsxWorkspace.ps1` — idempotent setup. Clones `MSXOrg/docs` and `MSXOrg/memory` under `~/.msx`, requires existing clones to exactly match their remote default branches, and writes a repository-local git identity so the workspace never modifies the global git config. -- `AGENTS.template.md` — the user-global entry instruction. It bootstraps the workspace, then points the agent at the docs and memory. Install it once per machine (below). +- `Initialize-MsxWorkspace.ps1` — the idempotent freshness gate for configured context repositories. +- `AGENTS.template.md` — the user-global entry instruction and first-run seed. -## The model +## Canonical repositories -- `~/.msx/docs` is **read context** — the ways of working, coding standards, and agent workflow. Changes to it go through **pull requests**. -- `~/.msx/docs.git` is the bare backing repository for the readable, clean `~/.msx/docs` main worktree. -- `~/.msx/memory` is **durable context** — notes and session history governed by that repository's contribution policy. -- `~/.msx/projects//docs.git` and `docs/` provide the same bare+main-worktree model for optional project docs; `memory/` remains a simple checkout. +| Source repository | Entry file | Published documentation | Visibility | Preferred local clone | +| --- | --- | --- | --- | --- | +| [MSXOrg/docs](https://github.com/MSXOrg/docs) | `src/docs/index.md` | | Public | `~/.msxorg/docs` | +| `MSXOrg/memory` | `index.md` | None | Private | `~/.msxorg/memory` | +| [PSModule/Process-PSModule](https://github.com/PSModule/Process-PSModule) | `docs/index.md` | | Public | `~/.psmodule/process-psmodule` | +| `PSModule/memory` | `index.md` | None | Private | `~/.psmodule/memory` | -> **Prerequisite:** `MSXOrg/memory` is a private repository — the bootstrap needs access to it (and working github.com credentials) to clone or update memory. +The documentation clones use a bare backing repository plus a clean default-branch worktree. The backing paths are `~/.msxorg/docs.git` and `~/.psmodule/process-psmodule.git`. Memory repositories remain simple checkouts. -Before either repository is used, bootstrap fetches it and requires a clean checkout on the remote default branch at the exact remote head. A dirty, locally ahead, diverged, wrong-branch, or unreachable context repository stops bootstrap; stale context is never treated as a successful fallback. +Private memory requires authenticated access. Failure to clone or refresh either private repository stops context resolution instead of falling back to an older copy. -Keeping the workspace separate and git-isolated means an agent reads the same docs and memory in every repository, and its commits there use the workspace identity rather than whatever the working repository or the global config happens to be set to. +## Freshness gate -The loaded `AGENTS.md` points to the roots; discovery happens in documentation. Start at `~/.msx/docs/src/docs/index.md`, follow Ways of Working to Workflow, infer the current stage, and read the linked procedure. Clear task language can shortcut stage selection, but no skill or instruction file owns a separate copy of the process. +Run bootstrap at the start of every agent session. It: -## Install (once per machine) +1. validates every configured repository identity and collision-free relative path; +2. clones missing repositories; +3. fetches existing repositories and resolves their remote default branches; +4. requires clean default-branch checkouts at the exact fetched remote heads; and +5. writes repository-local git identity without modifying global git configuration. -Run the bootstrap: +A dirty, locally ahead, diverged, wrong-branch, noncanonical, or unreachable repository stops the gate. Context is read only after every selected repository succeeds. -```powershell -$workspaceRoot = if ($env:MSX_WORKSPACE_ROOT) { $env:MSX_WORKSPACE_ROOT } else { Join-Path $HOME '.msx' } -$docsUrl = if ($env:MSX_DOCS_URL) { $env:MSX_DOCS_URL } else { 'https://github.com/MSXOrg/docs.git' } -$memoryUrl = if ($env:MSX_MEMORY_URL) { $env:MSX_MEMORY_URL } else { 'https://github.com/MSXOrg/memory.git' } -$docs = Join-Path $workspaceRoot 'docs' -$docsBacking = "$docs.git" -if ((Test-Path $docs) -and -not (Test-Path (Join-Path $docs '.git'))) { - throw "$docs exists but is not a git repository. Remove it and re-run." -} -if (-not (Test-Path (Join-Path $docs '.git'))) { - if (-not (Test-Path $docsBacking)) { - New-Item -ItemType Directory -Force -Path (Split-Path -Parent $docs) | Out-Null - git clone --bare $docsUrl $docsBacking - if ($LASTEXITCODE -ne 0) { - throw "Bare clone of MSXOrg/docs failed (exit $LASTEXITCODE). Check network access and credentials." - } - } - if ((git --git-dir=$docsBacking rev-parse --is-bare-repository) -ne 'true') { - throw "$docsBacking exists but is not a bare repository." - } - if ((git --git-dir=$docsBacking remote get-url origin) -ne $docsUrl) { - throw "$docsBacking origin does not match canonical $docsUrl." - } - $refspec = '+refs/heads/*:refs/remotes/origin/*' - if ($refspec -notin @(git --git-dir=$docsBacking config --get-all remote.origin.fetch)) { - git --git-dir=$docsBacking config --add remote.origin.fetch $refspec - if ($LASTEXITCODE -ne 0) { throw "Could not configure $docsBacking." } - } - git --git-dir=$docsBacking fetch origin --prune --quiet - if ($LASTEXITCODE -ne 0) { throw "Could not refresh $docsBacking. Do not use stale context." } - git --git-dir=$docsBacking remote set-head origin --auto | Out-Null - if ($LASTEXITCODE -ne 0) { throw "Could not detect the MSXOrg/docs default branch." } - $defaultRef = (git --git-dir=$docsBacking symbolic-ref --short refs/remotes/origin/HEAD | Out-String).Trim() - if ($LASTEXITCODE -ne 0) { throw "Could not resolve origin/HEAD in $docsBacking." } - $defaultBranch = $defaultRef -replace '^origin/', '' - $remoteHead = (git --git-dir=$docsBacking rev-parse $defaultRef | Out-String).Trim() - if ($LASTEXITCODE -ne 0) { throw "Could not resolve $defaultRef in $docsBacking." } - $localRef = "refs/heads/$defaultBranch" - $localHead = (git --git-dir=$docsBacking rev-parse --verify $localRef 2>$null | Out-String).Trim() - if ($LASTEXITCODE -eq 128) { - git --git-dir=$docsBacking update-ref $localRef $remoteHead - } elseif ($LASTEXITCODE -ne 0) { - throw "Could not inspect $localRef in $docsBacking." - } elseif ($localHead -ne $remoteHead) { - git --git-dir=$docsBacking merge-base --is-ancestor $localHead $remoteHead - if ($LASTEXITCODE -ne 0) { throw "$localRef is ahead or diverged in $docsBacking." } - if ("branch $localRef" -in @(git --git-dir=$docsBacking worktree list --porcelain)) { - throw "$localRef is checked out elsewhere. Update that worktree first." - } - git --git-dir=$docsBacking update-ref $localRef $remoteHead $localHead - } - if ($LASTEXITCODE -ne 0 -or (git --git-dir=$docsBacking rev-parse $localRef) -ne $remoteHead) { - throw "$localRef is not exactly synchronized with $defaultRef." - } - git --git-dir=$docsBacking worktree add $docs $defaultBranch - if ($LASTEXITCODE -ne 0) { - throw "Could not create the canonical MSXOrg/docs worktree at $docs." - } -} else { - if ((git -C $docs remote get-url origin) -ne $docsUrl) { - throw "$docs origin does not match canonical $docsUrl." - } - $refspec = '+refs/heads/*:refs/remotes/origin/*' - if ($refspec -notin @(git -C $docs config --get-all remote.origin.fetch)) { - git -C $docs config --add remote.origin.fetch $refspec - if ($LASTEXITCODE -ne 0) { - throw "Could not configure remote tracking branches for MSXOrg/docs (exit $LASTEXITCODE)." - } - } - git -C $docs fetch origin --prune --quiet - if ($LASTEXITCODE -ne 0) { - throw "git fetch of MSXOrg/docs failed (exit $LASTEXITCODE). Do not use stale context." - } - git -C $docs remote set-head origin --auto | Out-Null - if ($LASTEXITCODE -ne 0) { throw "Could not detect the MSXOrg/docs default branch." } - $defaultRef = (git -C $docs symbolic-ref --short refs/remotes/origin/HEAD | Out-String).Trim() - if ($LASTEXITCODE -ne 0) { throw "Could not resolve origin/HEAD in $docs." } - $defaultBranch = $defaultRef -replace '^origin/', '' - $branch = (git -C $docs branch --show-current | Out-String).Trim() - if ($branch -ne $defaultBranch) { - throw "$docs is on '$branch', not '$defaultBranch'. Switch branches before using this context." - } - if (@(git -C $docs status --porcelain).Count -gt 0) { - throw "$docs has uncommitted changes. Resolve them before using this context." - } - git -C $docs merge --ff-only --quiet $defaultRef - if ($LASTEXITCODE -ne 0) { - throw "MSXOrg/docs cannot fast-forward to $defaultRef. Do not use stale context." - } - if ((git -C $docs rev-parse HEAD) -ne (git -C $docs rev-parse $defaultRef)) { - throw "$docs is not exactly synchronized with $defaultRef. Reconcile local commits before using this context." - } -} -$projects = @( - @{ - Name = 'MSXOrg' - Path = '' - DocsUrl = $docsUrl - MemoryUrl = $memoryUrl - } -) -& (Join-Path $docs 'bootstrap/Initialize-MsxWorkspace.ps1') -Root $workspaceRoot -Project $projects -if ($LASTEXITCODE -ne 0) { - throw "MSX workspace synchronization failed. Do not read context until every repository is current." -} +## First installation + +Install `AGENTS.template.md` as the user-global agent instruction and run its first PowerShell block. The seed refreshes `MSXOrg/docs`, then invokes the canonical bootstrap script from that refreshed repository for all four sources. + +For Claude Code, route the user instruction to the refreshed template: + +```text +@~/.msxorg/docs/bootstrap/AGENTS.template.md ``` -## Add project context +Copilot reads user-level instructions natively. Repository `AGENTS.md` files stay thin routers and do not contain bootstrap logic. + +## Repository configuration -The default project is MSXOrg. A repository in another project declares additional docs and memory coordinates in its agent installation chapter and passes them to the same bootstrap: +The script accepts explicit repository coordinates. `Path` is relative to `Root`, which defaults to the current user's home directory. ```powershell -$projects = @( - @{ - Name = 'MSXOrg' - Path = '' - DocsUrl = 'https://github.com/MSXOrg/docs.git' - MemoryUrl = 'https://github.com/MSXOrg/memory.git' - } - @{ - Name = 'PSModule' - Path = 'projects/PSModule' - DocsUrl = 'https://github.com/PSModule/docs.git' - MemoryUrl = 'https://github.com/PSModule/memory.git' - } +$repositories = @( + @{ Name = 'MSXOrg/docs'; Path = '.msxorg/docs'; Url = 'https://github.com/MSXOrg/docs.git'; Kind = 'docs' } + @{ Name = 'MSXOrg/memory'; Path = '.msxorg/memory'; Url = 'https://github.com/MSXOrg/memory.git'; Kind = 'memory' } + @{ Name = 'PSModule/Process-PSModule'; Path = '.psmodule/process-psmodule'; Url = 'https://github.com/PSModule/Process-PSModule.git'; Kind = 'docs' } + @{ Name = 'PSModule/memory'; Path = '.psmodule/memory'; Url = 'https://github.com/PSModule/memory.git'; Kind = 'memory' } ) -& (Join-Path $docs 'bootstrap/Initialize-MsxWorkspace.ps1') -Project $projects +& ./Initialize-MsxWorkspace.ps1 -Repository $repositories ``` -Each plug-in uses the same fail-closed freshness validation. `Path` is relative to `~/.msx`, so projects can choose a collision-free location without forking the bootstrap. - -Existing clean simple docs clones are migrated automatically. The original clone is retained beside the new layout as `docs.simple-clone-backup` for manual verification and removal. Existing docs worktrees backed by another bare path are reused in place. Dirty, ahead, diverged, wrong-branch, conflicting-path, or otherwise unsafe layouts stop with actionable guidance before conversion. - -Docs changes use topic worktrees created from `~/.msx/docs.git`; never branch or work inside the canonical `~/.msx/docs` main worktree. +URLs are transport configuration, not repository identity. They may use any git transport that resolves the named source repository. -Wire it into the tools so it runs as the first instruction: +## Former `~/.msx/` layout -- **Claude Code** reads `CLAUDE.md`. Add an import to `~/.claude/CLAUDE.md`: +The former layout is never a fallback context source. When bootstrap finds one of these paths, it emits an actionable warning, leaves the path unchanged, and creates or refreshes the corresponding canonical clone: - ```text - @~/.msx/docs/bootstrap/AGENTS.template.md - ``` +| Former path | Canonical replacement | +| --- | --- | +| `~/.msx/docs` | `~/.msxorg/docs` | +| `~/.msx/memory` | `~/.msxorg/memory` | +| `~/.msx/projects/PSModule/docs` | `~/.psmodule/process-psmodule` | +| `~/.msx/projects/PSModule/memory` | `~/.psmodule/memory` | -- **Copilot** reads `AGENTS.md` natively. Install the contents of `AGENTS.template.md` as your **user-level** Copilot instructions so it applies in every repository. Per-repository `AGENTS.md` files stay thin pointers to the central docs — don't put the bootstrap there. +Verify the canonical clone before removing a former path. This copy-and-diagnose approach avoids trusting stale content, moving dirty work, or repairing a checkout destructively. -## Identity +Existing simple documentation clones already at a canonical path are migrated to the bare-plus-worktree layout only after they pass the freshness gate. The original clone is retained beside the new layout as `.simple-clone-backup` for manual verification and removal. Unsafe layouts stop with recovery guidance. -The script writes a repository-local git identity to each clone. The default is the maintainer's GitHub **noreply** identity, so no personal email is written into git config and commits still attribute to the maintainer. Override it with `-UserName` / `-UserEmail`, or point it at a dedicated agent account when one exists. +## Writing context -> **Override this if you are not the maintainer.** With the default, commits — including memory pushes to `main` — are attributed to the maintainer's account. Pass `-UserName` and `-UserEmail` (for example `-UserEmail 'you@users.noreply.github.com'`), or point the script at a dedicated agent account, so your commits are attributed correctly. +Documentation changes use topic worktrees created from the relevant bare backing repository; never work in a canonical context worktree. Memory follows the selected private repository's own `AGENTS.md` and `CONTRIBUTING.md`. diff --git a/tests/Initialize-MsxWorkspace.Tests.ps1 b/tests/Initialize-MsxWorkspace.Tests.ps1 index e4b9f0a..e493f6e 100644 --- a/tests/Initialize-MsxWorkspace.Tests.ps1 +++ b/tests/Initialize-MsxWorkspace.Tests.ps1 @@ -137,19 +137,25 @@ exit `$LASTEXITCODE } $runner = Join-Path $Fixture.Root "seed-$([IO.Path]::GetFileNameWithoutExtension($MarkdownPath)).ps1" Set-Content -LiteralPath $runner -Value $match.Groups[1].Value - $previousRoot = $env:MSX_WORKSPACE_ROOT - $previousDocs = $env:MSX_DOCS_URL - $previousMemory = $env:MSX_MEMORY_URL + $previousRoot = $env:MSX_CONTEXT_ROOT + $previousMsxDocs = $env:MSXORG_DOCS_URL + $previousMsxMemory = $env:MSXORG_MEMORY_URL + $previousPsmoduleDocs = $env:PSMODULE_DOCS_URL + $previousPsmoduleMemory = $env:PSMODULE_MEMORY_URL try { - $env:MSX_WORKSPACE_ROOT = $Workspace - $env:MSX_DOCS_URL = $Fixture.Remotes.docs - $env:MSX_MEMORY_URL = $Fixture.Remotes.memory + $env:MSX_CONTEXT_ROOT = $Workspace + $env:MSXORG_DOCS_URL = $Fixture.Remotes.docs + $env:MSXORG_MEMORY_URL = $Fixture.Remotes.memory + $env:PSMODULE_DOCS_URL = $Fixture.Remotes.docs + $env:PSMODULE_MEMORY_URL = $Fixture.Remotes.memory $output = & $script:pwsh -NoProfile -File $runner 2>&1 | Out-String return [pscustomobject]@{ ExitCode = $LASTEXITCODE; Output = $output } } finally { - $env:MSX_WORKSPACE_ROOT = $previousRoot - $env:MSX_DOCS_URL = $previousDocs - $env:MSX_MEMORY_URL = $previousMemory + $env:MSX_CONTEXT_ROOT = $previousRoot + $env:MSXORG_DOCS_URL = $previousMsxDocs + $env:MSXORG_MEMORY_URL = $previousMsxMemory + $env:PSMODULE_DOCS_URL = $previousPsmoduleDocs + $env:PSMODULE_MEMORY_URL = $previousPsmoduleMemory } } } @@ -672,19 +678,20 @@ exit `$LASTEXITCODE Should -BeNullOrEmpty } - It 'installs canonical topology from the seed block' -ForEach @( - @{ Name = 'agent template'; MarkdownPath = '../bootstrap/AGENTS.template.md' } - @{ Name = 'bootstrap README'; MarkdownPath = '../bootstrap/README.md' } - ) { + It 'installs canonical topology from the agent template seed block' { + $Name = 'agent template' + $MarkdownPath = '../bootstrap/AGENTS.template.md' $workspace = Join-Path $fixture.Root "seed-$($Name.Replace(' ', '-'))" $seedPath = Join-Path $PSScriptRoot $MarkdownPath $result = Invoke-BootstrapSeed -Fixture $fixture -MarkdownPath $seedPath -Workspace $workspace $result.ExitCode | Should -Be 0 -Because $result.Output - $docs = Join-Path $workspace 'docs' - $backing = Join-Path $workspace 'docs.git' - $memory = Join-Path $workspace 'memory' + $docs = Join-Path $workspace '.msxorg/docs' + $backing = Join-Path $workspace '.msxorg/docs.git' + $memory = Join-Path $workspace '.msxorg/memory' + $psmoduleDocs = Join-Path $workspace '.psmodule/process-psmodule' + $psmoduleMemory = Join-Path $workspace '.psmodule/memory' Test-Path -LiteralPath (Join-Path $docs '.git') -PathType Leaf | Should -BeTrue (Invoke-Git -Arguments @("--git-dir=$backing", 'rev-parse', '--is-bare-repository')).Trim() | Should -BeExactly 'true' @@ -694,6 +701,10 @@ exit `$LASTEXITCODE Should -BeExactly (Invoke-Git -WorkingDirectory $fixture.Writers.docs -Arguments @('rev-parse', 'HEAD')).Trim() Test-Path -LiteralPath (Join-Path $memory '.git') -PathType Container | Should -BeTrue -Because $result.Output + Test-Path -LiteralPath (Join-Path $psmoduleDocs '.git') -PathType Leaf | + Should -BeTrue -Because $result.Output + Test-Path -LiteralPath (Join-Path $psmoduleMemory '.git') -PathType Container | + Should -BeTrue -Because $result.Output (Invoke-Git -WorkingDirectory $docs -Arguments @('config', '--local', 'user.name')).Trim() | Should -BeExactly 'Marius Storhaug' (Invoke-BootstrapSeed -Fixture $fixture -MarkdownPath $seedPath -Workspace $workspace).ExitCode | @@ -702,8 +713,8 @@ exit `$LASTEXITCODE It 'refreshes a stale bare backing before the seed creates its canonical worktree' { $workspace = Join-Path $fixture.Root 'seed-stale-backing' - New-Item -ItemType Directory -Path $workspace | Out-Null - $backing = Join-Path $workspace 'docs.git' + New-Item -ItemType Directory -Path (Join-Path $workspace '.msxorg') -Force | Out-Null + $backing = Join-Path $workspace '.msxorg/docs.git' Invoke-Git -Arguments @('clone', '--bare', '--quiet', $fixture.Remotes.docs, $backing) | Out-Null Add-TestCommit -Repository $fixture.Writers.docs -Name 'Advance before seed' Invoke-Git -WorkingDirectory $fixture.Writers.docs -Arguments @('push', '--quiet') | Out-Null @@ -712,7 +723,7 @@ exit `$LASTEXITCODE $result = Invoke-BootstrapSeed -Fixture $fixture -MarkdownPath $script:agentTemplate -Workspace $workspace $result.ExitCode | Should -Be 0 -Because $result.Output - $docs = Join-Path $workspace 'docs' + $docs = Join-Path $workspace '.msxorg/docs' (Invoke-Git -Arguments @("--git-dir=$backing", 'rev-parse', 'main')).Trim() | Should -BeExactly $remoteHead (Invoke-Git -WorkingDirectory $docs -Arguments @('rev-parse', 'HEAD')).Trim() | Should -BeExactly $remoteHead } From 9799ad1ac198958fd52057f6f041bedcfe7c0505 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 29 Aug 2026 13:11:17 +0200 Subject: [PATCH 05/19] Clarify repository source freshness --- bootstrap/Initialize-MsxWorkspace.ps1 | 2 +- .../agentic-development/design.md | 2 +- .../Capabilities/agentic-development/index.md | 4 ++-- .../agentic-development/memory-template.md | 2 +- .../Capabilities/agentic-development/spec.md | 8 +++---- src/docs/Capabilities/index.md | 2 +- tests/Initialize-MsxWorkspace.Tests.ps1 | 22 +++++++++---------- 7 files changed, 21 insertions(+), 21 deletions(-) diff --git a/bootstrap/Initialize-MsxWorkspace.ps1 b/bootstrap/Initialize-MsxWorkspace.ps1 index b587994..bc3a83b 100644 --- a/bootstrap/Initialize-MsxWorkspace.ps1 +++ b/bootstrap/Initialize-MsxWorkspace.ps1 @@ -3,7 +3,7 @@ <# .SYNOPSIS - Clone or update canonical project context repositories in a git-isolated workspace under $HOME. + Clone or update canonical organization context repositories under $HOME. .DESCRIPTION The single starting point for every agent. It ensures each configured diff --git a/src/docs/Capabilities/agentic-development/design.md b/src/docs/Capabilities/agentic-development/design.md index d04155e..4692aed 100644 --- a/src/docs/Capabilities/agentic-development/design.md +++ b/src/docs/Capabilities/agentic-development/design.md @@ -346,7 +346,7 @@ Because Copilot code review reads the head branch, a pull request that changes ` 4. Add the canonical Workflow and linked stage procedures to `docs`. 5. Add starter memory sections to `memory`. 6. Add the `AGENTS.md` router to each product repository, plus a route for every client that cannot read it. -7. Add a bootstrap that keeps local docs and memory clones present and exactly synchronized before use. +7. Add a bootstrap that keeps preferred local documentation and memory clones present and exactly synchronized before use. 8. Review new work for pointer discipline: facts live once, links point to them. ## Where this connects diff --git a/src/docs/Capabilities/agentic-development/index.md b/src/docs/Capabilities/agentic-development/index.md index e2c1bb9..8a0728b 100644 --- a/src/docs/Capabilities/agentic-development/index.md +++ b/src/docs/Capabilities/agentic-development/index.md @@ -1,11 +1,11 @@ --- title: Agentic Development -description: The framework for org-scoped docs and memory repositories that give agents project-specific standards, working knowledge, and behavior. +description: The framework for repository-addressable organization documentation and memory that gives agents project-specific context. --- # Agentic Development -The Agentic Development framework makes an organization the operating boundary for human and agent work. Each organization owns a `docs` repository for canonical knowledge and a `memory` repository for accumulated working context; every product repository carries a short router that points to those roots, and keeps its own nuance in the files a human already reads. +The Agentic Development framework makes an organization the operating boundary for human and agent work. Each organization identifies a canonical documentation source repository and a private `memory` repository; every product repository carries a short router that names those sources and keeps its own nuance in the files a human already reads. A repository adopts the framework by carrying a short router and the client routes that reach it, and by letting agents read outward — the repository's own files first, then the organization documentation and memory, then the current task. The organization selects *which* context applies; the reading order decides what is read first. diff --git a/src/docs/Capabilities/agentic-development/memory-template.md b/src/docs/Capabilities/agentic-development/memory-template.md index 736aff5..6a0a708 100644 --- a/src/docs/Capabilities/agentic-development/memory-template.md +++ b/src/docs/Capabilities/agentic-development/memory-template.md @@ -157,7 +157,7 @@ of the shared history. `memory` repositories default to **private**. Working memory can capture internal context, half-finished reasoning, and organization-specific detail that isn't meant for a -public audience, even when the adjoining `docs` repository is public. +public audience, even when the adjoining documentation source is public. Privacy and the `session/` ignore rule solve different problems and neither substitutes for the other. Privacy decides *who* may read durable memory; the ignore rule decides *what* diff --git a/src/docs/Capabilities/agentic-development/spec.md b/src/docs/Capabilities/agentic-development/spec.md index 7afb4d6..9e1a78e 100644 --- a/src/docs/Capabilities/agentic-development/spec.md +++ b/src/docs/Capabilities/agentic-development/spec.md @@ -20,7 +20,7 @@ Product repositories do not copy that knowledge. They carry thin pointer files t This framework rests on the [Principles](../../Ways-of-Working/Principles/index.md): -- **[Documentation lives close to the thing it documents](../../Ways-of-Working/Principles/Engineering-Practices.md#documentation-lives-close-to-the-thing-it-documents).** Organization-wide ways of working live in the organization `docs` repository; repository-specific nuance lives in the repository. +- **[Documentation lives close to the thing it documents](../../Ways-of-Working/Principles/Engineering-Practices.md#documentation-lives-close-to-the-thing-it-documents).** Organization-wide ways of working live in the designated organization documentation source; repository-specific nuance lives in the repository. - **[Everything as Code](../../Ways-of-Working/Principles/Engineering-Practices.md#everything-as-code).** Standards and memory are plain files in git. Changes are reviewed, diffed, and reverted like code. - **[Written once, referenced everywhere](../../Ways-of-Working/Principles/Software-Design.md#dry-with-judgment).** Agent instructions point to canonical docs and memory rather than duplicating them. - **[AI-first development](../../Ways-of-Working/Principles/AI-First-Development.md).** Humans create durable context; agents consume that context and leave useful improvements behind. @@ -79,7 +79,7 @@ Applies to any organization that wants a shared project knowledge base and memor - **Named intents stay pointer-based.** A packaged shortcut for a recurring workflow — however a runtime names it — MUST resolve to the canonical documentation for that workflow and MUST contain only the runtime mechanics needed to get there. It MUST NOT restate the procedure, since a shortcut that carries a copy of the process becomes a second, silently diverging definition of it. - **Advice and authority are separate.** An automated agent MAY analyse work and publish its conclusion as advice on the artifact under review. It MUST NOT be the thing that decides: it MUST NOT overwrite a human's decision, MUST NOT re-apply a decision a human has changed, and MUST NOT commit to the branch it is advising on. Its output is an input to the review, not a substitute for it. - **Coordination happens on durable artifacts.** Where agents and humans coordinate, they MUST do so through the platform's own artifacts — issues, labels, and pull requests — rather than through a channel that leaves no trace in the repository. Intent MUST be separable from implementation: the issue states *what* is wanted and *why*, and the pull request proposes *how*, so that a rejected implementation does not discard the intent. -- **Reviewed knowledge changes.** Changes to the `docs` repository MUST happen through pull requests. Changes to memory MAY be lighter-weight, but MUST remain versioned in git. +- **Reviewed knowledge changes.** Changes to the designated documentation source MUST happen through pull requests. Changes to memory MAY be lighter-weight, but MUST remain versioned in git. - **No cross-project bleed.** An agent working in one organization MUST NOT apply another organization's standards or memory unless the current task explicitly asks for cross-organization work. - **Traceable memory.** Memory entries SHOULD identify the context they came from and SHOULD be short, factual, and linked to the relevant issue, pull request, document, or repository when one exists. @@ -87,14 +87,14 @@ Applies to any organization that wants a shared project knowledge base and memor - An agent working in `github.com/PSModule/` resolves `github.com/PSModule/Process-PSModule` and `github.com/PSModule/memory`, plus inherited `github.com/MSXOrg/docs` and `github.com/MSXOrg/memory`. - An agent working in `github.com/MSXOrg/` resolves `github.com/MSXOrg/docs` and `github.com/MSXOrg/memory` as the canonical project context. -- An agent working in `//` for any adopting organization resolves `//docs` and `//memory` as the canonical project context, with no change to the framework. +- An agent working in `//` for any adopting organization resolves the documentation and memory repositories declared by its router, with no change to the framework. - A new product repository can adopt the framework by adding a router and the client routes that reach it, without copying standards or memory pages. - An agent reads the repository's own README and CONTRIBUTING before it reads an organization standard, and still applies the organization standard when the two disagree. - A human can start at `docs/index.md` or `memory/index.md` and navigate to the same context an agent uses. - A human or agent can follow `docs/index.md` → Ways of Working → Workflow → the current stage procedure without knowing a file path in advance. - A prompt such as `Review this PR ` reaches the Review procedure directly, while `Make this issue ` reaches Define, without a parallel process definition. - A missing, dirty, locally ahead, diverged, wrong-branch, or unreachable preferred local clone stops local discovery before any context index is read; an agent may instead resolve the named source through another current access method. -- A working checkout of a `docs` repository present on disk is not read as canonical context, and a reader can tell a current checkout from a stale one before trusting either. +- A working checkout of a documentation source repository present on disk is not read as canonical context, and a reader can tell a current checkout from a stale one before trusting either. - Updating a standard in `docs` changes the canonical guidance without editing every repository. - Capturing a recurring lesson in `memory` makes it available to later agents working in the same organization. diff --git a/src/docs/Capabilities/index.md b/src/docs/Capabilities/index.md index 2d85da8..95f2fbb 100644 --- a/src/docs/Capabilities/index.md +++ b/src/docs/Capabilities/index.md @@ -28,7 +28,7 @@ the same spec-and-design shape as any other capability. | [Deployment](deployment/index.md) | How a change to managed resources is approved together with its effect and deployed exactly as approved — one spec, and one design for each combination of deploying a service provider from a CI/CD platform. | | [VS Code Extension Framework](vscode-extension-framework/index.md) | How a VS Code extension is built, tested, versioned, packaged, and published — one GitHub-native pipeline, opt-in from a template and a single settings file. | | [PowerShell on GitHub](powershell-on-github/index.md) | How we make GitHub a first-class platform for PowerShell through reusable modules, actions, and capability gaps we close over time. | -| [Agentic Development](agentic-development/index.md) | The framework for org-scoped docs and memory repositories that give agents project-specific standards, working knowledge, and behavior. | +| [Agentic Development](agentic-development/index.md) | The framework for repository-addressable organization documentation and memory that gives agents project-specific context. | diff --git a/tests/Initialize-MsxWorkspace.Tests.ps1 b/tests/Initialize-MsxWorkspace.Tests.ps1 index e493f6e..584276f 100644 --- a/tests/Initialize-MsxWorkspace.Tests.ps1 +++ b/tests/Initialize-MsxWorkspace.Tests.ps1 @@ -352,7 +352,7 @@ exit `$LASTEXITCODE } It 'installs additional context through explicit repository coordinates' { - $runner = Join-Path $fixture.Root 'invoke-project-bootstrap.ps1' + $runner = Join-Path $fixture.Root 'invoke-repository-bootstrap.ps1' $bootstrap = $script:bootstrap.Replace("'", "''") $workspace = $fixture.Workspace.Replace("'", "''") $docsRemote = $fixture.Remotes.docs.Replace("'", "''") @@ -371,23 +371,23 @@ exit `$LASTEXITCODE $output = & $script:pwsh -NoProfile -File $runner 2>&1 | Out-String $LASTEXITCODE | Should -Be 0 -Because $output - $projectDocs = Join-Path $fixture.Workspace 'projects/Project/process' - $projectMemory = Join-Path $fixture.Workspace 'projects/Project/memory' - Test-Path -LiteralPath (Join-Path $projectDocs '.git') | Should -BeTrue - Test-Path -LiteralPath (Join-Path $projectMemory '.git') | Should -BeTrue + $additionalDocs = Join-Path $fixture.Workspace 'projects/Project/process' + $additionalMemory = Join-Path $fixture.Workspace 'projects/Project/memory' + Test-Path -LiteralPath (Join-Path $additionalDocs '.git') | Should -BeTrue + Test-Path -LiteralPath (Join-Path $additionalMemory '.git') | Should -BeTrue Test-Path -LiteralPath (Join-Path $fixture.Workspace 'projects/Project/process.git') | Should -BeTrue (Invoke-Git -Arguments @( "--git-dir=$(Join-Path $fixture.Workspace 'projects/Project/process.git')", 'rev-parse', '--is-bare-repository' )).Trim() | Should -BeExactly 'true' - (Invoke-Git -WorkingDirectory $projectDocs -Arguments @('rev-parse', 'HEAD')).Trim() | + (Invoke-Git -WorkingDirectory $additionalDocs -Arguments @('rev-parse', 'HEAD')).Trim() | Should -BeExactly (Invoke-Git -WorkingDirectory $fixture.Writers.docs -Arguments @('rev-parse', 'HEAD')).Trim() - (Invoke-Git -WorkingDirectory $projectMemory -Arguments @('rev-parse', 'HEAD')).Trim() | + (Invoke-Git -WorkingDirectory $additionalMemory -Arguments @('rev-parse', 'HEAD')).Trim() | Should -BeExactly (Invoke-Git -WorkingDirectory $fixture.Writers.memory -Arguments @('rev-parse', 'HEAD')).Trim() } - It 'rejects duplicate project paths after normalization' { + It 'rejects duplicate repository paths after normalization' { $runner = Join-Path $fixture.Root 'invoke-duplicate-bootstrap.ps1' $bootstrap = $script:bootstrap.Replace("'", "''") $workspace = $fixture.Workspace.Replace("'", "''") @@ -408,7 +408,7 @@ exit `$LASTEXITCODE $output | Should -Match 'Repository paths overlap' } - It 'rejects duplicate project names before mutation' -ForEach @( + It 'rejects duplicate repository names before mutation' -ForEach @( @{ SecondPath = '' } @{ SecondPath = 'docs' } ) { @@ -443,7 +443,7 @@ exit `$LASTEXITCODE Should -BeNullOrEmpty } - It 'rejects project paths overlapping canonical context storage' -ForEach @( + It 'rejects repository paths overlapping canonical context storage' -ForEach @( @{ UnsafePath = 'docs' } @{ UnsafePath = 'docs.git' } @{ UnsafePath = 'memory' } @@ -490,7 +490,7 @@ exit `$LASTEXITCODE Should -BeNullOrEmpty } - It 'rejects overlapping non-empty project roots before mutation' { + It 'rejects overlapping non-empty repository paths before mutation' { $runner = Join-Path $fixture.Root 'invoke-overlapping-roots.ps1' $bootstrap = $script:bootstrap.Replace("'", "''") $workspace = $fixture.Workspace.Replace("'", "''") From 82e9b5f59101a5d5a260964dd4ca7fe727318dda Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 29 Aug 2026 13:19:39 +0200 Subject: [PATCH 06/19] Treat context paths as literal values --- bootstrap/Initialize-MsxWorkspace.ps1 | 45 ++++++++++++++----------- tests/Initialize-MsxWorkspace.Tests.ps1 | 30 +++++++++++++++++ 2 files changed, 56 insertions(+), 19 deletions(-) diff --git a/bootstrap/Initialize-MsxWorkspace.ps1 b/bootstrap/Initialize-MsxWorkspace.ps1 index bc3a83b..c776c7a 100644 --- a/bootstrap/Initialize-MsxWorkspace.ps1 +++ b/bootstrap/Initialize-MsxWorkspace.ps1 @@ -386,10 +386,13 @@ foreach ($repository in $contextRepositories) { foreach ($repository in $contextRepositories | Where-Object Kind -eq 'memory') { $memoryPath = Join-Path $Root $repository.RelativePath $memoryGitEntry = Join-Path $memoryPath '.git' - if (Test-Path $memoryGitEntry -PathType Leaf) { + if (Test-Path -LiteralPath $memoryGitEntry -PathType Leaf) { throw "Memory context '$memoryPath' is a worktree, but memory requires a simple checkout with a .git directory." } - if ((Test-Path $memoryPath) -and -not (Test-Path $memoryGitEntry -PathType Container)) { + if ( + (Test-Path -LiteralPath $memoryPath) -and + -not (Test-Path -LiteralPath $memoryGitEntry -PathType Container) + ) { throw "Memory context '$memoryPath' is not a supported simple git checkout." } } @@ -397,18 +400,18 @@ foreach ($repository in $contextRepositories | Where-Object Kind -eq 'memory') { foreach ($repository in $contextRepositories) { $contextPath = Join-Path $Root $repository.RelativePath $gitEntry = Join-Path $contextPath '.git' - if ($repository.Kind -eq 'memory' -and (Test-Path $gitEntry -PathType Container)) { + if ($repository.Kind -eq 'memory' -and (Test-Path -LiteralPath $gitEntry -PathType Container)) { Assert-ContextOrigin -GitPath $contextPath -RepositoryUrl $repository.Url } elseif ($repository.Kind -eq 'docs') { - if (Test-Path $gitEntry -PathType Container) { + if (Test-Path -LiteralPath $gitEntry -PathType Container) { Assert-ContextOrigin -GitPath $contextPath -RepositoryUrl $repository.Url - } elseif (Test-Path $gitEntry -PathType Leaf) { + } elseif (Test-Path -LiteralPath $gitEntry -PathType Leaf) { $commonDir = (git -C $contextPath rev-parse --path-format=absolute --git-common-dir | Out-String).Trim() if ($LASTEXITCODE -ne 0) { throw "Cannot resolve docs backing repository for '$contextPath'." } Assert-ContextOrigin -GitPath $commonDir -RepositoryUrl $repository.Url -Bare - } elseif (Test-Path "$contextPath.git") { + } elseif (Test-Path -LiteralPath "$contextPath.git") { Assert-ContextOrigin -GitPath "$contextPath.git" -RepositoryUrl $repository.Url -Bare } } @@ -422,11 +425,11 @@ $results = foreach ($repo in $contextRepositories) { $path = Join-Path $Root $repo.RelativePath if ($repo.Kind -eq 'memory') { $memoryGitEntry = Join-Path $path '.git' - if (Test-Path $memoryGitEntry -PathType Leaf) { + if (Test-Path -LiteralPath $memoryGitEntry -PathType Leaf) { throw "Memory context '$path' is a worktree, but memory requires a simple checkout with a .git directory." } - if (-not (Test-Path $memoryGitEntry -PathType Container)) { - if (Test-Path $path) { + if (-not (Test-Path -LiteralPath $memoryGitEntry -PathType Container)) { + if (Test-Path -LiteralPath $path) { throw "Cannot clone memory into '$path': it exists but is not a supported simple git checkout." } if ($PSCmdlet.ShouldProcess($repo.Url, "Clone memory into '$path'")) { @@ -451,15 +454,15 @@ $results = foreach ($repo in $contextRepositories) { $expectedBackingPath = "$path.git" $backingPath = $null $gitEntry = Join-Path $path '.git' - if (Test-Path $gitEntry -PathType Container) { + if (Test-Path -LiteralPath $gitEntry -PathType Container) { # Safe simple-clone migration: synchronize first, preserve all refs in a # new bare backing repository, and retain the old clone as a backup. $remote = Sync-ContextCheckout -Path $path -RepositoryUrl $repo.Url -Confirm:$false - if (Test-Path $expectedBackingPath) { + if (Test-Path -LiteralPath $expectedBackingPath) { throw "Cannot migrate '$path': backing path '$expectedBackingPath' already exists." } $backupPath = "$path.simple-clone-backup" - if (Test-Path $backupPath) { + if (Test-Path -LiteralPath $backupPath) { throw "Cannot migrate '$path': backup path '$backupPath' already exists. Reconcile it first." } if ($PSCmdlet.ShouldProcess($path, "Migrate simple clone to '$expectedBackingPath'")) { @@ -482,7 +485,7 @@ $results = foreach ($repo in $contextRepositories) { throw "Bare backing repository '$expectedBackingPath' did not preserve every local branch and tag." } } catch { - if (Test-Path $expectedBackingPath) { + if (Test-Path -LiteralPath $expectedBackingPath) { Remove-Item -LiteralPath $expectedBackingPath -Recurse -Force } throw "Migration preparation failed for '$path'; the original clone is unchanged. $($_.Exception.Message)" @@ -506,7 +509,7 @@ $results = foreach ($repo in $contextRepositories) { } catch { $activationError = $_ $rollbackErrors = [Collections.Generic.List[string]]::new() - if ($moved -and (Test-Path $path)) { + if ($moved -and (Test-Path -LiteralPath $path)) { git --git-dir=$expectedBackingPath worktree remove --force $path 2>$null if ($LASTEXITCODE -ne 0) { $rollbackErrors.Add("git worktree remove failed for '$path'.") @@ -517,14 +520,18 @@ $results = foreach ($repo in $contextRepositories) { $rollbackErrors.Add("Could not remove partial worktree '$path': $($_.Exception.Message)") } } - if ($moved -and -not (Test-Path $path) -and (Test-Path $backupPath)) { + if ( + $moved -and + -not (Test-Path -LiteralPath $path) -and + (Test-Path -LiteralPath $backupPath) + ) { try { Move-Item -LiteralPath $backupPath -Destination $path -ErrorAction Stop } catch { $rollbackErrors.Add("Could not restore '$backupPath' to '$path': $($_.Exception.Message)") } } - if (Test-Path $expectedBackingPath) { + if (Test-Path -LiteralPath $expectedBackingPath) { try { Remove-Item -LiteralPath $expectedBackingPath -Recurse -Force -ErrorAction Stop } catch { @@ -539,7 +546,7 @@ $results = foreach ($repo in $contextRepositories) { Write-Warning "Migrated '$path' to bare+worktree layout. Verify it, then remove retained backup '$backupPath'." } $backingPath = $expectedBackingPath - } elseif (Test-Path $gitEntry -PathType Leaf) { + } elseif (Test-Path -LiteralPath $gitEntry -PathType Leaf) { $backingPath = (git -C $path rev-parse --path-format=absolute --git-common-dir | Out-String).Trim() if ($LASTEXITCODE -ne 0) { throw "Cannot resolve the backing repository for docs worktree '$path'." @@ -548,11 +555,11 @@ $results = foreach ($repo in $contextRepositories) { if ($LASTEXITCODE -ne 0 -or $isBare -ne 'true') { throw "Docs worktree '$path' is not backed by a bare repository. Repair it before using context." } - } elseif (Test-Path $path) { + } elseif (Test-Path -LiteralPath $path) { throw "Cannot install docs at '$path': it exists but is not a supported git checkout." } else { $backingPath = $expectedBackingPath - if (-not (Test-Path $backingPath)) { + if (-not (Test-Path -LiteralPath $backingPath)) { if ($PSCmdlet.ShouldProcess($repo.Url, "Clone bare docs backing into '$backingPath'")) { New-Item -ItemType Directory -Path (Split-Path -Parent $backingPath) -Force | Out-Null git clone --bare --quiet $repo.Url $backingPath diff --git a/tests/Initialize-MsxWorkspace.Tests.ps1 b/tests/Initialize-MsxWorkspace.Tests.ps1 index 584276f..3c2a813 100644 --- a/tests/Initialize-MsxWorkspace.Tests.ps1 +++ b/tests/Initialize-MsxWorkspace.Tests.ps1 @@ -387,6 +387,36 @@ exit `$LASTEXITCODE Should -BeExactly (Invoke-Git -WorkingDirectory $fixture.Writers.memory -Arguments @('rev-parse', 'HEAD')).Trim() } + It 'treats configured repository paths literally during preflight' { + $literalRoot = Join-Path $fixture.Root 'literal-path-workspace' + New-Item -ItemType Directory -Path (Join-Path $literalRoot 'context1/docs/.git') -Force | Out-Null + New-Item -ItemType Directory -Path (Join-Path $literalRoot 'context1/memory/.git') -Force | Out-Null + $runner = Join-Path $fixture.Root 'invoke-literal-path-bootstrap.ps1' + $bootstrap = $script:bootstrap.Replace("'", "''") + $docsRemote = $fixture.Remotes.docs.Replace("'", "''") + $memoryRemote = $fixture.Remotes.memory.Replace("'", "''") + @" +`$repositories = @( + @{ Name = 'Literal/docs'; Path = 'context[1]/docs'; Url = '$docsRemote'; Kind = 'docs' } + @{ Name = 'Literal/memory'; Path = 'context[1]/memory'; Url = '$memoryRemote'; Kind = 'memory' } +) +& '$bootstrap' -Root '$literalRoot' -Repository `$repositories -UserName 'Fixture User' -UserEmail 'fixture@example.invalid' +exit `$LASTEXITCODE +"@ | Set-Content -LiteralPath $runner + + $output = & $script:pwsh -NoProfile -File $runner 2>&1 | Out-String + + $LASTEXITCODE | Should -Be 0 -Because $output + Test-Path -LiteralPath (Join-Path $literalRoot 'context[1]/docs/.git') -PathType Leaf | + Should -BeTrue + Test-Path -LiteralPath (Join-Path $literalRoot 'context[1]/memory/.git') -PathType Container | + Should -BeTrue + Test-Path -LiteralPath (Join-Path $literalRoot 'context1/docs/.git') -PathType Container | + Should -BeTrue + Test-Path -LiteralPath (Join-Path $literalRoot 'context1/memory/.git') -PathType Container | + Should -BeTrue + } + It 'rejects duplicate repository paths after normalization' { $runner = Join-Path $fixture.Root 'invoke-duplicate-bootstrap.ps1' $bootstrap = $script:bootstrap.Replace("'", "''") From 8b2f9426d6a04830f22fb4371afaf1977e969a63 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 29 Aug 2026 13:28:25 +0200 Subject: [PATCH 07/19] Create context directories from literal paths --- bootstrap/Initialize-MsxWorkspace.ps1 | 6 +++--- tests/Initialize-MsxWorkspace.Tests.ps1 | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/bootstrap/Initialize-MsxWorkspace.ps1 b/bootstrap/Initialize-MsxWorkspace.ps1 index c776c7a..6da77f8 100644 --- a/bootstrap/Initialize-MsxWorkspace.ps1 +++ b/bootstrap/Initialize-MsxWorkspace.ps1 @@ -418,7 +418,7 @@ foreach ($repository in $contextRepositories) { } if ($PSCmdlet.ShouldProcess($Root, 'Create workspace root')) { - New-Item -ItemType Directory -Force -Path $Root | Out-Null + [void] [IO.Directory]::CreateDirectory($Root) } $results = foreach ($repo in $contextRepositories) { @@ -433,7 +433,7 @@ $results = foreach ($repo in $contextRepositories) { throw "Cannot clone memory into '$path': it exists but is not a supported simple git checkout." } if ($PSCmdlet.ShouldProcess($repo.Url, "Clone memory into '$path'")) { - New-Item -ItemType Directory -Path (Split-Path -Parent $path) -Force | Out-Null + [void] [IO.Directory]::CreateDirectory((Split-Path -Parent $path)) git clone --quiet $repo.Url $path if ($LASTEXITCODE -ne 0) { throw "git clone failed for $($repo.Url) (exit $LASTEXITCODE). Check access and credentials." @@ -561,7 +561,7 @@ $results = foreach ($repo in $contextRepositories) { $backingPath = $expectedBackingPath if (-not (Test-Path -LiteralPath $backingPath)) { if ($PSCmdlet.ShouldProcess($repo.Url, "Clone bare docs backing into '$backingPath'")) { - New-Item -ItemType Directory -Path (Split-Path -Parent $backingPath) -Force | Out-Null + [void] [IO.Directory]::CreateDirectory((Split-Path -Parent $backingPath)) git clone --bare --quiet $repo.Url $backingPath if ($LASTEXITCODE -ne 0) { throw "Bare clone failed for $($repo.Url) (exit $LASTEXITCODE)." diff --git a/tests/Initialize-MsxWorkspace.Tests.ps1 b/tests/Initialize-MsxWorkspace.Tests.ps1 index 3c2a813..0c88183 100644 --- a/tests/Initialize-MsxWorkspace.Tests.ps1 +++ b/tests/Initialize-MsxWorkspace.Tests.ps1 @@ -388,7 +388,8 @@ exit `$LASTEXITCODE } It 'treats configured repository paths literally during preflight' { - $literalRoot = Join-Path $fixture.Root 'literal-path-workspace' + $literalRoot = Join-Path $fixture.Root 'literal-path-workspace[1]' + [void] [IO.Directory]::CreateDirectory((Join-Path $fixture.Root 'literal-path-workspace1')) New-Item -ItemType Directory -Path (Join-Path $literalRoot 'context1/docs/.git') -Force | Out-Null New-Item -ItemType Directory -Path (Join-Path $literalRoot 'context1/memory/.git') -Force | Out-Null $runner = Join-Path $fixture.Root 'invoke-literal-path-bootstrap.ps1' From 2a52f2ff7124d64bc9073f389ace7eb1a3eef2f5 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 29 Aug 2026 13:34:59 +0200 Subject: [PATCH 08/19] Create seed directories from literal paths --- bootstrap/AGENTS.template.md | 2 +- tests/Initialize-MsxWorkspace.Tests.ps1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bootstrap/AGENTS.template.md b/bootstrap/AGENTS.template.md index 37b189e..d621c2d 100644 --- a/bootstrap/AGENTS.template.md +++ b/bootstrap/AGENTS.template.md @@ -21,7 +21,7 @@ if ((Test-Path -LiteralPath $docs) -and -not (Test-Path -LiteralPath (Join-Path } if (-not (Test-Path -LiteralPath (Join-Path $docs '.git'))) { if (-not (Test-Path -LiteralPath $docsBacking)) { - New-Item -ItemType Directory -Force -Path (Split-Path -Parent $docs) | Out-Null + [void] [IO.Directory]::CreateDirectory((Split-Path -Parent $docs)) git clone --bare $msxDocsUrl $docsBacking if ($LASTEXITCODE -ne 0) { throw "Bare clone of MSXOrg/docs failed (exit $LASTEXITCODE). Check network access and credentials." diff --git a/tests/Initialize-MsxWorkspace.Tests.ps1 b/tests/Initialize-MsxWorkspace.Tests.ps1 index 0c88183..c797968 100644 --- a/tests/Initialize-MsxWorkspace.Tests.ps1 +++ b/tests/Initialize-MsxWorkspace.Tests.ps1 @@ -712,7 +712,7 @@ exit `$LASTEXITCODE It 'installs canonical topology from the agent template seed block' { $Name = 'agent template' $MarkdownPath = '../bootstrap/AGENTS.template.md' - $workspace = Join-Path $fixture.Root "seed-$($Name.Replace(' ', '-'))" + $workspace = Join-Path $fixture.Root "seed-$($Name.Replace(' ', '-'))[1]" $seedPath = Join-Path $PSScriptRoot $MarkdownPath $result = Invoke-BootstrapSeed -Fixture $fixture -MarkdownPath $seedPath -Workspace $workspace From 089cf2ebbfc5bb073e9725f3572f4a5d3150935b Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 30 Aug 2026 13:33:57 +0200 Subject: [PATCH 09/19] Route agents through documentation sources --- AGENTS.md | 4 + .../agentic-development/AGENTS.template.md | 31 +++-- .../agentic-development/conformance.md | 6 +- .../agentic-development/design.md | 119 ++++++++++-------- .../Capabilities/agentic-development/index.md | 4 +- .../runtime-integration.md | 37 +++--- .../Capabilities/agentic-development/spec.md | 50 ++++---- src/docs/Capabilities/index.md | 2 +- src/docs/Ways-of-Working/Git-Worktrees.md | 2 +- 9 files changed, 147 insertions(+), 108 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 2dafcea..dbca462 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,7 +1,11 @@ # AGENTS +Read nearest first and always use the newest version. + Read in this order: 1. README.md - about the repo and what it contains 2. .github/CONTRIBUTING.md - how a change is made and reviewed 3. src/docs/index.md - the documentation this repository owns + +Repository-local guidance may add nuance but does not override organization or inherited standards. diff --git a/src/docs/Capabilities/agentic-development/AGENTS.template.md b/src/docs/Capabilities/agentic-development/AGENTS.template.md index 7ba9c74..c612347 100644 --- a/src/docs/Capabilities/agentic-development/AGENTS.template.md +++ b/src/docs/Capabilities/agentic-development/AGENTS.template.md @@ -12,11 +12,10 @@ block into an `AGENTS.md` at the repository root. The router moves from the most specific guidance to the least specific: repository-local guidance first, initiative-specific guidance next, and the organization's central guidance last. -Before using a linked repository, clone it locally, keep its configuration local -to that clone, and update it from its remote. -Agentic runtimes and local development may materialize that repository in any -context checkout they control. Clone, freshness, and local configuration -mechanics belong to that runtime or development setup, not to this portable +Each route names its source repository, entry file, published documentation, +and preferred local clone. An agent may use a CLI, the web, published +documentation, or a refreshed local clone. Clone and local configuration +mechanics belong to the runtime or development setup, not to this portable router. Client-specific files such as `.claude/CLAUDE.md` and @@ -27,15 +26,31 @@ pointers to canonical documentation pages. ````markdown # AGENTS +Read nearest first and always use the newest version. + Read in this order: 1. `README.md` — what this repository is and how it builds. 2. `.github/CONTRIBUTING.md` — how a change is made and reviewed here. 3. `docs/index.md` — this repository's own documentation. -4. [MSXOrg/docs](https://github.com/MSXOrg/docs/) — the organization standards. +4. [MSXOrg/docs](https://github.com/MSXOrg/docs/) — organization standards; + entry file `src/docs/index.md`; published at ; + preferred clone `~/.msxorg/docs`. + +Use a CLI, the web, published documentation, or a refreshed local clone, +whichever provides the newest accessible source. -Clone each linked repository locally, keep its configuration local to that -clone, and update it before reading it. +Repository-local guidance may add nuance but does not override organization or +inherited standards. ```` + +A PSModule repository inserts this initiative route before `MSXOrg/docs`: + +```markdown +4. [PSModule/Process-PSModule](https://github.com/PSModule/Process-PSModule/) — + PSModule process and standards; entry file `docs/index.md`; published at + ; preferred clone + `~/.psmodule/process-psmodule`. +``` diff --git a/src/docs/Capabilities/agentic-development/conformance.md b/src/docs/Capabilities/agentic-development/conformance.md index 00fe305..a321b2b 100644 --- a/src/docs/Capabilities/agentic-development/conformance.md +++ b/src/docs/Capabilities/agentic-development/conformance.md @@ -22,9 +22,9 @@ A conformant repository MUST provide all of the following. | **A router agent file** | The repository root holds a single agent instruction file, and it routes rather than instructs ([design](design.md#pointer-files)) | | **Reading order** | The router states the order in which context is read, from repository-local to organization-canonical | | **Client routes** | Every supported runtime's expected instruction path exists and resolves to the router, carrying no content of its own ([client behavior](design.md#client-behavior)) | -| **Canonical coordinates** | The router names the organization's canonical documentation location, so context is reachable without prior knowledge | -| **Freshness** | Canonical context is synchronized at the start of every session, in every runtime ([context freshness](design.md#context-freshness)) | -| **Precedence** | The router states that local files never override a standard | +| **Canonical coordinates** | The router names each source repository, entry file, published documentation when available, and preferred clone | +| **Freshness** | The router requires the newest accessible source, and any local clone is synchronized before use ([context freshness](design.md#context-freshness)) | +| **Precedence** | The router states that repository-local guidance does not override organization or inherited standards | The baseline is small on purpose. Every item is something an agent needs before it can find anything else; nothing on the list is a judgement about how the repository should be diff --git a/src/docs/Capabilities/agentic-development/design.md b/src/docs/Capabilities/agentic-development/design.md index 6503215..f64ab17 100644 --- a/src/docs/Capabilities/agentic-development/design.md +++ b/src/docs/Capabilities/agentic-development/design.md @@ -5,7 +5,7 @@ description: How the agentic development framework is built — OKF documentatio # Agentic Development — Design -The behavior in the [spec](spec.md) is delivered by an organization-level documentation repository, adopted by each product repository through thin pointer files. The design keeps project knowledge in one reviewed place and lets each agent runtime adapt without copying process knowledge. +The behavior in the [spec](spec.md) is delivered by repository-addressable documentation sources, adopted by each product repository through thin pointer files. The design keeps project knowledge in one reviewed place and lets each agent runtime adapt without copying process knowledge. ## Organization anatomy @@ -13,26 +13,26 @@ The GitHub organization is the project boundary. The host distinguishes work fro ```text // - docs/ # canonical knowledge base; changes through pull requests - / # product or component repository + / # canonical knowledge base; changes through pull requests + / # product or component repository / ``` -Current project scopes follow the same shape: +Current project scopes identify these sources: -| Host | Organization | Docs | -| --- | --- | --- | -| `github.com` | `MSXOrg` | `MSXOrg/docs` | -| `github.com` | `PSModule` | `PSModule/docs` | -| `` | `` | `/docs` | +| Host | Organization | Documentation source | Entry file | Published documentation | Preferred clone | +| --- | --- | --- | --- | --- | --- | +| `github.com` | `MSXOrg` | `MSXOrg/docs` | `src/docs/index.md` | | `~/.msxorg/docs` | +| `github.com` | `PSModule` | `PSModule/Process-PSModule` | `docs/index.md` | | `~/.psmodule/process-psmodule` | +| `` | `` | Designated `/` | Declared by the router | Declared by the router | Declared by the router | -The last row is the general case: any adopting organization on any GitHub host — public or an enterprise instance — plugs into the same shape without changing the framework. +The last row is the general case. Repository identity remains stable whether an agent uses a CLI, the web, published documentation, or a refreshed local clone. ## Repository roles -### `docs` +### Documentation source -The `docs` repository is the canonical knowledge base. It owns: +The designated documentation source is the canonical knowledge base. It owns: - vision, principles, and ways of working; - coding standards and documentation standards; @@ -40,7 +40,7 @@ The `docs` repository is the canonical knowledge base. It owns: - project glossary and onboarding; - the canonical Workflow and its linked stage procedures. -Changes to `docs` happen through pull requests because this repository defines durable project intent. +Changes happen through pull requests because the source defines durable project intent. `MSXOrg/docs` owns cross-organization guidance. `PSModule/Process-PSModule` owns PSModule process and standards and inherits from `MSXOrg/docs`. ### Product repositories @@ -64,7 +64,7 @@ The repository owns only repository-specific nuance, and each kind has a file th ## OKF page model -The `docs` repository uses the [Open Knowledge Format](../../Dictionary/index.md#open-knowledge-format) style: Markdown with YAML frontmatter, one concept per page, paths as stable identity, and indexes as navigation maps. +Documentation sources use the [Open Knowledge Format](../../Dictionary/index.md#open-knowledge-format) style: Markdown with YAML frontmatter, one concept per page, paths as stable identity, and indexes as navigation maps. Minimum page frontmatter: @@ -102,14 +102,14 @@ flowchart TD start["Agent receives task"] --> policy["System and client policy"] policy --> user["User-global preferences"] user --> pointer["Read AGENTS.md pointer"] - pointer --> locate["Resolve host, org, and docs root"] + pointer --> locate["Resolve documentation sources"] locate --> host{"Which project scope?"} host -->|"github.com/MSXOrg"| msx["MSXOrg context"] host -->|"github.com/PSModule"| psmodule["PSModule context"] host -->|"any adopting org"| other["<host>/<org> context"] - msx --> refresh["Synchronize selected docs with Git
stop unless exactly synchronized"] + msx --> refresh["Resolve newest source version
refresh local clones before use"] psmodule --> refresh other --> refresh refresh --> repo["Read README, CONTRIBUTING,
and local docs"] @@ -131,28 +131,42 @@ Resolution is deterministic. If the active repository remote is `github.com/PSMo ## Pointer files -`AGENTS.md` is the cross-runtime router. It lists where to read, in order, and -includes one instruction to prepare linked repositories before reading them. It -holds no detailed synchronization mechanics, build commands, contribution -mechanics, or standards. +`AGENTS.md` is the cross-runtime router. It lists where to read, identifies each +source, and requires the newest accessible version without selecting an access +tool. It holds no detailed synchronization mechanics, build commands, +contribution mechanics, or standards. ```markdown # AGENTS +Read nearest first and always use the newest version. + Read in this order: 1. `README.md` — what this repository is and how it builds. 2. `.github/CONTRIBUTING.md` — how a change is made and reviewed here. 3. `docs/index.md` — this repository's own documentation. -4. [MSXOrg/docs](https://github.com/MSXOrg/docs/) — the organization standards. +4. [MSXOrg/docs](https://github.com/MSXOrg/docs/) — organization standards; + entry file `src/docs/index.md`; published at ; + preferred clone `~/.msxorg/docs`. + +Use a CLI, the web, published documentation, or a refreshed local clone, +whichever provides the newest accessible source. -Clone each linked repository locally, keep its configuration local to that -clone, and update it before reading it. +Repository-local guidance may add nuance but does not override organization or +inherited standards. +``` + +A PSModule repository inserts its initiative source before `MSXOrg/docs`: -Read nearest first. A local file never overrides a standard. +```markdown +4. [PSModule/Process-PSModule](https://github.com/PSModule/Process-PSModule/) — + PSModule process and standards; entry file `docs/index.md`; published at + ; preferred clone + `~/.psmodule/process-psmodule`. ``` -A router lists the destinations that exist in that repository, written as the paths that repository actually uses — the ones above are an example, not a required layout. A repository with no documentation of its own drops that line; one that publishes the standards resolves steps 3 and 4 to the same tree and drops the duplicate. Writing a real path matters more than matching the example, because the router is read literally. +A router lists only destinations that apply to its repository. A repository with no documentation of its own drops that line; one that publishes the standards resolves local and organization documentation to the same source and drops the duplicate. The route does not require a particular client or access method. A local clone is usable only after its freshness gate succeeds. The index trail is the default. A clear prompt can shortcut stage discovery: `Review this PR ` enters Review, `Make this issue ` enters Define, and `Implement ` enters Implement. These phrases are routing hints interpreted by [Workflow](../../Ways-of-Working/Workflow.md#find-the-current-stage), not commands with independent procedures. @@ -178,20 +192,21 @@ Path-scoped instruction files are reserved for local rules that cannot live cent ## Local workspace -A local Git clone makes central context predictable: +A preferred local clone makes documentation context predictable: ```text ~/.msxorg/ docs/ # clean MSXOrg/docs clone ~/.psmodule/ - docs/ # clean PSModule/docs clone + process-psmodule/ # clean PSModule/Process-PSModule clone ``` -Before context is read, the agent ensures the clone exists, fetches its remote, -and fast-forwards its default branch. Each clone must be clean, checked out on -the remote default branch, and exactly equal to the fetched remote head. A -dirty, locally ahead, diverged, wrong-branch, or unreachable clone stops context -resolution; the agent does not use a possibly stale local copy. +When an agent uses a local clone, it ensures the clone exists, fetches its +remote, and fast-forwards its default branch before reading. Each clone must be +clean, checked out on the remote default branch, and exactly equal to the +fetched remote head. A dirty, locally ahead, diverged, wrong-branch, or +unreachable clone stops local resolution; the agent does not use a stale copy. +Remote CLI, web, and published documentation remain valid current sources. Each GitHub organization has its own organization-named workspace root, such as `~/.msxorg` for MSXOrg or `~/.psmodule` for PSModule. Repository agent files @@ -200,37 +215,37 @@ guidance defines how a context checkout is prepared and verified. ## Context freshness -The freshness gate is only worth as much as the last time it ran. A clone +The local freshness gate is only worth as much as the last time it ran. A clone synchronized once is current at that moment and progressively less so afterwards, and an agent reading a week-old clone reads a standard that has since changed while believing it is canonical. -So Git synchronization runs at the **start of every session**, not once per -machine. What differs between runtimes is where the trigger hangs, never what -it does: +When a runtime uses local clones, Git synchronization runs at the **start of +every session**, not once per machine. What differs between runtimes is where +the trigger hangs, never what it does: | Runtime shape | Lifecycle point | How context freshness is established | | --- | --- | --- | -| Local interactive agent | Session start | The agent fetches and fast-forwards the context clone before the first turn. | -| Hosted or remote agent | Environment setup | The environment's setup steps clone or synchronize the context repository while the workspace is being prepared. | +| Local interactive agent | Session start | The agent resolves a current remote source or fetches and fast-forwards a preferred clone before the first turn. | +| Hosted or remote agent | Environment setup | Setup provides current documentation through a remote route or a freshly prepared clone. | | Review-time agent | Pull request event | Instructions are read from the pull request's head branch, so freshness follows the branch under review rather than a local clone. | -| Batch or scheduled agent | Job start | The job's first step clones or synchronizes the context repository; a scheduled run has no earlier lifecycle point to rely on. | +| Batch or scheduled agent | Job start | The job resolves current documentation before acting; a scheduled run has no earlier lifecycle point to rely on. | -Each of these is one **declaration** of the same behavior. The runtime ensures -the clone is clean, on the remote default branch, and exactly equal to the -fetched head before context is read. A runtime may use its own lifecycle hook, -or the agent may perform the Git check explicitly. +Each of these is one **declaration** of the same behavior: use the newest +accessible source. When that source is a local clone, the runtime ensures it is +clean, on the remote default branch, and exactly equal to the fetched head +before context is read. The synchronization MUST be idempotent, because it runs far more often than it changes anything. A process that is expensive or noisy when everything is already current gets disabled, and a disabled process is worse than no process, because the workspace still appears synchronized. -Where a runtime offers no lifecycle point at all, Git synchronization MUST be -invoked explicitly before context is read. It MUST NOT be skipped on the -grounds that the workspace was synchronized recently; "recently" is not a state -the agent can observe, and the gate exists precisely to replace that judgment -with a check. +Where a runtime uses local clones but offers no lifecycle point, Git +synchronization MUST be invoked explicitly before context is read. It MUST NOT +be skipped on the grounds that the workspace was synchronized recently; +"recently" is not a state the agent can observe, and the gate exists precisely +to replace that judgment with a check. Each shape's obligations beyond context freshness — its entry file, tool declaration, and identity — are set out in [Runtime Integration](runtime-integration.md). @@ -254,7 +269,7 @@ Because Copilot code review reads the head branch, a pull request that changes ` | Failure | Design response | | --- | --- | | Repository does not identify its organization context | Infer from remote URL; ask when ambiguous. | -| A docs clone is missing or cannot synchronize | Clone or repair it with Git, then retry. Stop context resolution until the canonical context repository passes the freshness gate. | +| A preferred clone is missing or cannot synchronize | Use a current remote route, or clone or repair it before reading locally. Never use the stale clone as fallback. | | Pointer file duplicates central standards | Replace duplicated content with a route during review. A client file holds a pointer, not a copy. | | A skill, command, named agent, or instruction file defines a workflow stage | Delete the duplicate procedure and link to Workflow or its stage page. | | Two organizations are open in one workspace | Select by active repository; ask before cross-project changes. | @@ -263,10 +278,10 @@ Because Copilot code review reads the head branch, a pull request that changes ` ## Adoption path -1. Create or identify the organization `docs` repository. -2. Add the canonical Workflow and linked stage procedures to `docs`. +1. Create or identify the organization's canonical documentation source. +2. Add the canonical Workflow and linked stage procedures to that source. 3. Add the `AGENTS.md` router to each product repository, plus a route for every client that cannot read it. -4. Document the canonical docs clone and require Git synchronization before use. +4. Document source entry files, published documentation, and preferred clones; require Git synchronization only when a clone is used. 5. Review new work for pointer discipline: facts live once, links point to them. ## Where this connects diff --git a/src/docs/Capabilities/agentic-development/index.md b/src/docs/Capabilities/agentic-development/index.md index b681eb2..a33e4b3 100644 --- a/src/docs/Capabilities/agentic-development/index.md +++ b/src/docs/Capabilities/agentic-development/index.md @@ -1,11 +1,11 @@ --- title: Agentic Development -description: The framework for org-scoped documentation that gives agents project-specific standards and behavior. +description: The framework for repository-addressable organization documentation that gives agents project-specific standards and behavior. --- # Agentic Development -The Agentic Development framework makes an organization the operating boundary for human and agent work. Each organization owns a `docs` repository for canonical knowledge; every product repository carries a short router that points to that root, and keeps its own nuance in the files a human already reads. +The Agentic Development framework makes an organization the operating boundary for human and agent work. Each organization identifies the repository that owns its canonical knowledge; every product repository carries a short router that names the applicable sources and keeps its own nuance in the files a human already reads. A repository adopts the framework by carrying a short router and the client routes that reach it, and by letting agents read outward — the repository's own files first, then the organization documentation, then the current task. The organization selects *which* context applies; the reading order decides what is read first. diff --git a/src/docs/Capabilities/agentic-development/runtime-integration.md b/src/docs/Capabilities/agentic-development/runtime-integration.md index ddfb9cd..18f5bd3 100644 --- a/src/docs/Capabilities/agentic-development/runtime-integration.md +++ b/src/docs/Capabilities/agentic-development/runtime-integration.md @@ -19,7 +19,7 @@ MUST supply, and nothing else. | Obligation | What it means | Where it is defined | | --- | --- | --- | | **Entry file** | The instruction file the runtime reads first, which routes to the canonical router rather than restating it | [Pointer files](design.md#pointer-files) | -| **Lifecycle point** | The moment before the first turn where the runtime verifies and synchronizes context | [Context freshness](design.md#context-freshness) | +| **Lifecycle point** | The moment before the first turn where the runtime verifies that context is current | [Context freshness](design.md#context-freshness) | | **Tool declaration** | The shared tool server set, expressed in the runtime's own configuration format | [MCP Servers](mcp-servers.md#same-contract-different-declaration-syntax) | | **Identity** | The credential the runtime authenticates with, and the permissions that identity holds | [Permissions](#permissions-follow-the-identity-not-the-runtime) | @@ -45,8 +45,9 @@ Four shapes cover the field: | **Review-time** | Triggered by a platform event on a pull request | Reads instructions from the branch under review, not from a local clone | | **Scheduled** | On a timer, with no human present | No earlier lifecycle point exists, and no one is watching a failure | -The same Git synchronization contract, the same router, and the same tool contract serve all -four. What changes is only where synchronization runs. +The same freshness contract, router, and tool contract serve all four. What +changes is how the runtime reaches the named source and, when it uses a local +clone, where synchronization runs. ### Local interactive @@ -54,21 +55,23 @@ The durable workspace is the hazard. A local runtime is the only shape whose con survives between sessions, which means it is the only shape that can read a week-old standard while believing it is canonical. -So Git synchronization MUST attach to a session-start lifecycle point in the runtime's own -configuration, and it MUST run before the first turn rather than on first use of context. +When the runtime uses local clones, Git synchronization MUST attach to a +session-start lifecycle point in the runtime's own configuration and run before +the first turn rather than on first use of context. -Where the runtime offers no session-start point, Git synchronization MUST be invoked explicitly -before context is read. +Where the runtime offers no session-start point, local clones MUST be +synchronized explicitly before context is read. A runtime MAY instead use a +current remote CLI, web, or published-documentation route. ### Hosted A hosted runtime gets a fresh workspace per run, so staleness is not the risk — *absence* is. The environment either establishes context during setup or the agent works without it. -Git synchronization therefore belongs in the environment's setup steps, and setup failure MUST fail -the run. An agent that starts successfully against missing context produces work that looks -finished and was never governed, which is the most expensive failure in the set because it is -the one that reaches review looking normal. +Context preparation therefore belongs in the environment's setup steps, and +failure MUST fail the run. The environment may clone and synchronize the source +or provide current remote access. An agent that starts successfully against +missing context produces work that looks finished and was never governed. ### Review-time @@ -82,10 +85,10 @@ carefully as code, since they are live before merge. ### Scheduled -A scheduled runtime has no lifecycle point earlier than the job itself, so Git synchronization -is the job's first step. It also has no human to notice a problem, which raises the bar on -failure handling: a scheduled run MUST fail loudly and MUST NOT proceed with partial context, -because a silent partial run repeats on the schedule. +A scheduled runtime has no lifecycle point earlier than the job itself, so +context preparation is the job's first step. It also has no human to notice a +problem, which raises the bar on failure handling: a scheduled run MUST fail +loudly and MUST NOT proceed with partial context. ## Permissions follow the identity, not the runtime @@ -118,8 +121,8 @@ Adding a runtime is a documentation change plus four declarations, in this order 1. Identify its **shape** from the table above; the shape determines the lifecycle point. 2. Add its **entry file** as a route to the canonical router, carrying no process content. -3. Attach Git synchronization to its lifecycle point, preserving the clean, default-branch, - fast-forward-only contract. +3. Attach source freshness verification to its lifecycle point. For local + clones, preserve the clean, default-branch, fast-forward-only contract. 4. Declare the **shared tool set** in the runtime's native configuration format. 5. Record the **identity** it authenticates as and the permissions that identity holds. diff --git a/src/docs/Capabilities/agentic-development/spec.md b/src/docs/Capabilities/agentic-development/spec.md index 182bb0b..3d3f28b 100644 --- a/src/docs/Capabilities/agentic-development/spec.md +++ b/src/docs/Capabilities/agentic-development/spec.md @@ -9,16 +9,17 @@ description: Requirements for fresh, index-first agentic development through can An agent does useful work only when it knows which project it is serving, which standards apply, and what the team has already learned. That context MUST be project-scoped, durable, reviewable, and readable by humans and agents alike. The project boundary is the GitHub organization — `github.com/MSXOrg`, `github.com/PSModule`, and any other organization that adopts the framework, on any GitHub host. -Each organization owns a canonical repository: +Each organization identifies a canonical documentation source repository: -- `docs` — the reviewed knowledge base: vision, standards, workflows, specs, designs, glossary, onboarding, and project-wide rules. -Product repositories do not copy that knowledge. They carry thin pointer files that identify the organization context and direct agents to the relevant `docs` root before acting. +- The documentation source is the reviewed knowledge base: vision, standards, workflows, specs, designs, glossary, onboarding, and project-wide rules. It may be named `docs`, such as `MSXOrg/docs`, or be the repository that owns an initiative's process and standards, such as `PSModule/Process-PSModule`. + +Product repositories do not copy that knowledge. They carry thin pointer files that identify the applicable documentation sources before acting. ### Principles This framework rests on the [Principles](../../Ways-of-Working/Principles/index.md): -- **[Documentation lives close to the thing it documents](../../Ways-of-Working/Principles/Engineering-Practices.md#documentation-lives-close-to-the-thing-it-documents).** Organization-wide ways of working live in the organization `docs` repository; repository-specific nuance lives in the repository. +- **[Documentation lives close to the thing it documents](../../Ways-of-Working/Principles/Engineering-Practices.md#documentation-lives-close-to-the-thing-it-documents).** Organization-wide ways of working live in the organization's documentation source; repository-specific nuance lives in the repository. - **[Everything as Code](../../Ways-of-Working/Principles/Engineering-Practices.md#everything-as-code).** Standards are plain files in git. Changes are reviewed, diffed, and reverted like code. - **[Written once, referenced everywhere](../../Ways-of-Working/Principles/Software-Design.md#dry-with-judgment).** Agent instructions point to canonical docs rather than duplicating them. - **[AI-first development](../../Ways-of-Working/Principles/AI-First-Development.md).** Humans create durable context; agents consume that context and leave useful improvements behind. @@ -29,7 +30,7 @@ Applies to any organization that wants a shared project knowledge base for agent **In scope** -- Organization-level `docs` repository. +- Organization-level documentation source repositories. - Markdown documents with YAML frontmatter, following the [Open Knowledge Format](../../Dictionary/index.md#open-knowledge-format) model. - Thin repository pointer files: a required `AGENTS.md` router, and a route to it for every client that cannot read it. - Path-scoped rule files, reserved for local caveats that cannot live in repository or central documentation. @@ -51,41 +52,42 @@ Applies to any organization that wants a shared project knowledge base for agent ## Requirements - **Organization is the project boundary.** The framework MUST resolve project context from the Git host and organization before resolving repository-specific context. -- **Canonical docs repository.** Each adopting organization MUST have a `docs` repository that owns the reviewed knowledge base. -- **Predictable project context.** Repository-level agent instructions MUST identify the canonical documentation repository with a public repository pointer for each adopting organization. +- **Canonical documentation source.** Each adopting organization MUST identify the repository that owns its reviewed knowledge base. +- **Repository identity is authoritative.** A router MUST name each source as `/`. CLI, web, published-site, and refreshed-local-clone access are interchangeable delivery methods. +- **Predictable project context.** Repository-level agent instructions MUST identify each applicable public documentation source, its entry file, published documentation when available, and its preferred local clone. - **OKF-style documents.** Knowledge documents MUST be Markdown files with YAML frontmatter, one primary concept per page, and stable paths that act as identity. - **Small pages and indexes.** Documentation SHOULD prefer small pages, each folder SHOULD have an `index.md`, and indexes MUST let a human or agent navigate inward from the root. -- **Thin pointer files.** Product repositories MUST carry an `AGENTS.md` at the repository root that routes an agent from the repository's own files outward to the organization documentation and any inherited ecosystem documentation. It MUST be limited to that route list and the single context-preparation instruction defined by the template. It MUST NOT duplicate standards, workflow stages, or reusable process knowledge, and MUST NOT carry detailed synchronization procedures, build commands, or contribution mechanics. -- **Refresh-first, index-first workflow discovery.** After every canonical context repository passes the Git freshness gate, a human or agent MUST be able to follow the docs root index to Ways of Working, the canonical Workflow, and the procedure for the current stage. +- **Thin pointer files.** Product repositories MUST carry an `AGENTS.md` at the repository root that routes an agent from the repository's own files outward to organization and inherited ecosystem documentation. It MUST lead with `Read nearest first and always use the newest version.` and contain only the route list, source coordinates, access-neutral freshness instruction, and authority statement defined by the template. It MUST NOT duplicate standards, workflow stages, reusable process knowledge, detailed synchronization procedures, build commands, or contribution mechanics. +- **Freshness-first, index-first workflow discovery.** After every canonical source is resolved to its newest accessible version, a human or agent MUST be able to follow its entry index to the applicable workflow and current stage procedure. - **Stage resolution from work.** Agents MUST infer the current stage from the prompt and current artifacts. Explicit task language MAY shortcut to the matching stage, but the shortcut MUST resolve to the canonical documentation. - **One process source.** Skills, commands, named agents, and tool-specific instruction files MUST NOT redefine Workflow stages. A client convenience MAY link to a stage procedure and add only runtime mechanics. - **Segmentation before loading.** An agent MUST segment work by host, organization, repository, path, and task before loading project standards. The active repository context supplies the coordinates that make this possible; a per-repository router MUST NOT restate them. - **Client routes.** A runtime that cannot read `AGENTS.md` under its own filename MUST be given a route file — `.claude/CLAUDE.md`, `.github/copilot-instructions.md`, or the equivalent path for that runtime. A route file MUST contain only a pointer to `AGENTS.md` plus, at most, genuinely runtime-specific configuration that cannot be expressed as documentation. It MUST NOT restate standards, describe workflow behavior, or repeat the reading order. Duplication is a property of content rather than of filenames: a route holds nothing that can drift, so the number of route files is unconstrained while their contents are strictly limited. [Client behavior](design.md#client-behavior) names the exact set an MSX repository carries; an adopting organization MAY carry a different set for the runtimes it uses. - **Reading order and authority order are distinct.** An agent MUST read nearest context first, in the order the repository router defines. Precedence on conflict MUST run the opposite way: repository-local files MAY add nuance and narrow exceptions but MUST NOT override an organization or inherited ecosystem standard unless that standard permits a local exception. -- **Deterministic context resolution.** Agents MUST resolve context in layers: system and client policy, user preferences, the repository router, the context-repository Git freshness gate, repository context, path-scoped repository rules, organization docs, any inherited ecosystem docs, then current task context. -- **Local-first availability.** The docs repository SHOULD be available locally in a predictable workspace so agents can read it without relying on search or web access. -- **Fresh context before use.** Every canonical context repository MUST be fetched and exactly synchronized with its remote default branch before its contents are read. Agents use Git directly; dirty, locally ahead, diverged, wrong-branch, or unreachable repositories MUST stop context resolution rather than fall back to stale content. -- **Working checkouts are not context sources.** Canonical context MUST be read from the documentation repository clone that passed the freshness gate. A working checkout of the `docs` repository — one cloned in order to change it rather than to be governed by it — MUST NOT be used as a context source, whatever path it occupies, because it sits outside the gate. -- **Synchronize once per session, not once per machine.** The freshness gate MUST run at the start of every agent session, in every runtime. A workspace that was synchronized at some earlier point MUST NOT be treated as current, because elapsed time is not a state the agent can observe. The agent MUST use Git to synchronize it or stop when the clone cannot be safely synchronized. +- **Deterministic context resolution.** Agents MUST resolve context in layers: system and client policy, user preferences, the repository router, source freshness, repository context, path-scoped repository rules, organization documentation, inherited ecosystem documentation, then current task context. +- **Predictable local availability.** Preferred clones SHOULD use organization-addressable paths. MSXOrg uses `~/.msxorg/docs`; PSModule uses `~/.psmodule/process-psmodule`. +- **Fresh context before use.** Agents MUST use the newest accessible source version. Remote CLI, web, and published documentation MAY satisfy this directly. A local clone MUST be fetched and exactly synchronized with its remote default branch before its contents are read. Dirty, locally ahead, diverged, wrong-branch, or unreachable local clones MUST stop local resolution rather than become stale fallbacks. +- **Working checkouts are not context sources.** A local context source MUST be the preferred clone that passed the freshness gate. A working checkout cloned to change the documentation MUST NOT be used as canonical context unless it independently passes the same gate. +- **Synchronize local clones once per session, not once per machine.** When a runtime uses preferred local clones, the freshness gate MUST run at the start of every agent session. A clone synchronized at an earlier point MUST NOT be treated as current. - **One tool layer, declared per runtime.** Where agents use external tools, the set of tool servers MUST be defined once as a logical layer and each runtime MUST declare that same set in its own native configuration format. A runtime MUST NOT define tools of its own that other runtimes lack, because a capability available in one client and absent in another makes the documented procedure conditional on which client is running it. - **Named intents stay pointer-based.** A packaged shortcut for a recurring workflow — however a runtime names it — MUST resolve to the canonical documentation for that workflow and MUST contain only the runtime mechanics needed to get there. It MUST NOT restate the procedure, since a shortcut that carries a copy of the process becomes a second, silently diverging definition of it. - **Advice and authority are separate.** An automated agent MAY analyse work and publish its conclusion as advice on the artifact under review. It MUST NOT be the thing that decides: it MUST NOT overwrite a human's decision, MUST NOT re-apply a decision a human has changed, and MUST NOT commit to the branch it is advising on. Its output is an input to the review, not a substitute for it. - **Coordination happens on durable artifacts.** Where agents and humans coordinate, they MUST do so through the platform's own artifacts — issues, labels, and pull requests — rather than through a channel that leaves no trace in the repository. Intent MUST be separable from implementation: the issue states *what* is wanted and *why*, and the pull request proposes *how*, so that a rejected implementation does not discard the intent. -- **Reviewed knowledge changes.** Changes to the `docs` repository MUST happen through pull requests. +- **Reviewed knowledge changes.** Changes to a canonical documentation source MUST happen through pull requests. - **No cross-project bleed.** An agent working in one organization MUST NOT apply another organization's standards unless the current task explicitly asks for cross-organization work. ## Success criteria -- An agent working in `github.com/PSModule/` reads PSModule docs, not another organization's rules. +- An agent working in `github.com/PSModule/` resolves `github.com/PSModule/Process-PSModule` and inherited `github.com/MSXOrg/docs`. - An agent working in `github.com/MSXOrg/` resolves `github.com/MSXOrg/docs` as the canonical project context. -- An agent working in `//` for any adopting organization resolves `//docs` as the canonical project context, with no change to the framework. +- An agent working in `//` for any adopting organization resolves the documentation sources declared by its router, with no change to the framework. - A new product repository can adopt the framework by adding a router and the client routes that reach it, without copying standards pages. -- An agent reads the repository's own README and CONTRIBUTING before it reads an organization standard, and still applies the organization standard when the two disagree. +- An agent reads the repository's own `README.md` and `.github/CONTRIBUTING.md` before it reads an organization standard, and still applies the organization standard when the two disagree. - A human or agent can follow `docs/index.md` → Ways of Working → Workflow → the current stage procedure without knowing a file path in advance. - A prompt such as `Review this PR ` reaches the Review procedure directly, while `Make this issue ` reaches Define, without a parallel process definition. -- A missing, dirty, locally ahead, diverged, wrong-branch, or unreachable canonical context repository stops discovery before any context index is read. -- A working checkout of a `docs` repository present on disk is not read as canonical context, and a reader can tell a current checkout from a stale one before trusting either. -- Updating a standard in `docs` changes the canonical guidance without editing every repository. +- A dirty, locally ahead, diverged, wrong-branch, or unreachable preferred clone stops local discovery before any context index is read. +- A reader can distinguish a current preferred clone from a working checkout or stale clone before trusting it. +- Updating a standard in its source repository changes the canonical guidance without editing every repository. ## Context resolution contract @@ -93,11 +95,11 @@ The framework uses this normative reading order: 1. **System and client policy** — non-project instructions imposed by the agent runtime. 2. **User-global preferences** — the human operator's baseline style and risk posture. -3. **Repository router** — `AGENTS.md` identifies the host, organization, and the context sources below, in the order they are read. -4. **Freshness gate** — fetch every canonical context repository and stop unless each clean default-branch checkout exactly matches its remote head. +3. **Repository router** — `AGENTS.md` identifies the applicable source repositories and the order in which they are read. +4. **Freshness gate** — use the newest accessible source; when using a local clone, fetch it and stop local resolution unless its clean default-branch checkout exactly matches the remote head. 5. **Repository context** — README, CONTRIBUTING, local docs, and narrow repository exceptions. 6. **Path-scoped repository rules** — local rules that apply to the files being read, generated, reviewed, or edited. -7. **Organization documentation** — the `docs` repository for the resolved organization: start at `docs/index.md`, traverse to Ways of Working and Workflow, resolve the current stage, then load the relevant standards, specs, and designs. +7. **Organization documentation** — the designated documentation source for the resolved organization: start at its declared entry file, resolve the applicable workflow and current stage, then load relevant standards, specs, and designs. 8. **Inherited ecosystem documentation** — where the organization inherits from a broader standard set, the layer it inherits from. 9. **Current task context** — issue, pull request, prompt, branch, diff, diagnostics, terminal output, and open files; use these artifacts to re-evaluate the stage after each handoff. diff --git a/src/docs/Capabilities/index.md b/src/docs/Capabilities/index.md index b3b57f5..296b38d 100644 --- a/src/docs/Capabilities/index.md +++ b/src/docs/Capabilities/index.md @@ -28,7 +28,7 @@ the same spec-and-design shape as any other capability. | [Deployment](deployment/index.md) | How a change to managed resources is approved together with its effect and deployed exactly as approved — one spec, and one design for each combination of deploying a service provider from a CI/CD platform. | | [VS Code Extension Framework](vscode-extension-framework/index.md) | How a VS Code extension is built, tested, versioned, packaged, and published — one GitHub-native pipeline, opt-in from a template and a single settings file. | | [PowerShell on GitHub](powershell-on-github/index.md) | How we make GitHub a first-class platform for PowerShell through reusable modules, actions, and capability gaps we close over time. | -| [Agentic Development](agentic-development/index.md) | The framework for org-scoped documentation that gives agents project-specific standards and behavior. | +| [Agentic Development](agentic-development/index.md) | The framework for repository-addressable organization documentation that gives agents project-specific standards and behavior. | diff --git a/src/docs/Ways-of-Working/Git-Worktrees.md b/src/docs/Ways-of-Working/Git-Worktrees.md index d5980cd..3bd0409 100644 --- a/src/docs/Ways-of-Working/Git-Worktrees.md +++ b/src/docs/Ways-of-Working/Git-Worktrees.md @@ -43,7 +43,7 @@ In a single ordinary clone the opposite is forced: one branch checked out at a t - **`-/`** — one worktree folder per repository-delivery Task or Bug in flight, named by issue number and a short slug. The folder is a concise local path; its branch uses the required `/-` name, so the two names do not need to match. Canonical documentation context is a normal Git clone, such as -`~/.msxorg/docs` or `~/.psmodule/docs`, and is not part of this worktree +`~/.msxorg/docs` or `~/.psmodule/process-psmodule`, and is not part of this worktree topology. The bare-clone layout applies to delivery repositories only. ## Remotes From a6f71d83bc20c4d7c2667188a9025cfca4cfed64 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 30 Aug 2026 13:34:03 +0200 Subject: [PATCH 10/19] Remove shared memory guidance --- .../repository-governance/design.md | 7 +++--- src/docs/Coding-Standards/Natural-Language.md | 22 ++++--------------- .../Principles/AI-First-Development.md | 2 +- 3 files changed, 8 insertions(+), 23 deletions(-) diff --git a/src/docs/Capabilities/repository-governance/design.md b/src/docs/Capabilities/repository-governance/design.md index 7c0fa65..57fd91b 100644 --- a/src/docs/Capabilities/repository-governance/design.md +++ b/src/docs/Capabilities/repository-governance/design.md @@ -58,7 +58,7 @@ definition of the same control, and two definitions are two truths | Ruleset | Selects | Branches | Enforces | | --- | --- | --- | --- | | **Baseline protection** | Every type except Unmanaged | Protected branches | No deletion, no force-push, required checks | -| **Pull-request gate** | Every type except Unmanaged and Memory | Protected branches | Pull request required | +| **Pull-request gate** | Every type except Unmanaged | Protected branches | Pull request required | | **Artifact history** | Type includes Artifact | Default branch or Infrastructure integration branch | Squash-only merge, linear history required | | **Promotion — integration** | Type includes Infrastructure | Integration branch | Squash-only merge | | **Promotion — production** | Type includes Infrastructure | Production branch | Merge-commit only, promotion-source check required | @@ -72,9 +72,8 @@ Two properties of this table matter more than its contents: Automatic deletion of a merged pull request's head branch is not a ruleset rule. Reconciliation verifies the repository-level `delete_branch_on_merge` setting for -every governed repository instead. Memory therefore retains the protection, -check, review, and branch-cleanup baseline while being exempt only from the -pull-request gate; Unmanaged is the sole type that removes the baseline. +every governed repository instead. Unmanaged is the sole type that removes the +baseline. Bypass is granted on each ruleset to a **named administrative group in pull-request mode only** — never to individuals, and never as a blanket write diff --git a/src/docs/Coding-Standards/Natural-Language.md b/src/docs/Coding-Standards/Natural-Language.md index 3e947fc..9edb0db 100644 --- a/src/docs/Coding-Standards/Natural-Language.md +++ b/src/docs/Coding-Standards/Natural-Language.md @@ -5,7 +5,7 @@ description: Which language each artifact is written in, and the plain-language # Natural Language -Natural language is source code for humans and agents. It drives issues, pull requests, documentation, prompts, comments, error messages, release notes, and memory. Write it with the same care as code: clear, testable, consistent, and easy to change. +Natural language is source code for humans and agents. It drives issues, pull requests, documentation, prompts, comments, error messages, and release notes. Write it with the same care as code: clear, testable, consistent, and easy to change. This standard defines which language each artifact is written in, and how English prose is written in the MSX ecosystem. The project dialect is **American English (`en-US`)**. @@ -122,9 +122,8 @@ Before editing: 1. Resolve the host, organization, repository, path, and task. 2. Read the organization docs index. -3. Read relevant organization memory. -4. Read the repository README and local instructions. -5. Apply path-specific instructions for files being changed. +3. Read the repository README and local instructions. +4. Apply path-specific instructions for files being changed. ``` Avoid: @@ -182,7 +181,7 @@ Prompts are requests, not guesses. A good prompt names the desired outcome, the Prefer: ```text -Create a spec and design for org-scoped agent docs and memory in MSXOrg/docs. Follow the existing spec/design documentation model and use American English. +Create a spec and design for org-scoped agent documentation in MSXOrg/docs. Follow the existing spec/design documentation model and use American English. ``` Avoid: @@ -191,19 +190,6 @@ Avoid: Make something for agents. ``` -## Memory notes - -Memory notes should be short, factual, and reusable. They should not be a transcript of a session. - -Include: - -- the durable lesson; -- the affected project or repository; -- links to the issue, PR, file, or command that proves it; -- the date when the fact was learned, if timing matters. - -Do not include secrets, private personal notes, or speculation. - ## Where this connects - [Documentation](Documentation.md) — where documentation lives and what it explains. diff --git a/src/docs/Ways-of-Working/Principles/AI-First-Development.md b/src/docs/Ways-of-Working/Principles/AI-First-Development.md index 7f07142..5f3478f 100644 --- a/src/docs/Ways-of-Working/Principles/AI-First-Development.md +++ b/src/docs/Ways-of-Working/Principles/AI-First-Development.md @@ -33,7 +33,7 @@ Agent context is delivered through three layers, in priority order: 1. **Documentation** — the primary source. Published documentation, READMEs, and issue bodies are written for humans and naturally consumable by agents. 2. **Canonical workflow** — one documented process owns the order of work and links to ordinary documentation for each stage procedure. Indexes provide the default discovery path; clear task language may shortcut stage selection without creating separate instructions. -3. **Local pointer files** — each repository's agent router, and the content-free client routes that reach it, which read outward from the repository's own files to the organization's documentation, and to memory last. +3. **Local pointer files** — each repository's agent router, and the content-free client routes that reach it, which read outward from the repository's own files to the applicable organization and initiative documentation. ## Augmentation, not replacement From 10dbae35192d307bf42b1e55655e968de56bbc62 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 30 Aug 2026 13:39:56 +0200 Subject: [PATCH 11/19] Align router source metadata --- AGENTS.md | 7 ++++++- src/docs/Coding-Standards/Natural-Language.md | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index dbca462..739bdac 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -6,6 +6,11 @@ Read in this order: 1. README.md - about the repo and what it contains 2. .github/CONTRIBUTING.md - how a change is made and reviewed -3. src/docs/index.md - the documentation this repository owns +3. [MSXOrg/docs](https://github.com/MSXOrg/docs/) - this repository's + documentation; entry file `src/docs/index.md`; published at + ; preferred clone `~/.msxorg/docs` + +Use a CLI, the web, published documentation, or a refreshed local clone, +whichever provides the newest accessible source. Repository-local guidance may add nuance but does not override organization or inherited standards. diff --git a/src/docs/Coding-Standards/Natural-Language.md b/src/docs/Coding-Standards/Natural-Language.md index 9edb0db..d3c6f13 100644 --- a/src/docs/Coding-Standards/Natural-Language.md +++ b/src/docs/Coding-Standards/Natural-Language.md @@ -121,7 +121,7 @@ Prefer: Before editing: 1. Resolve the host, organization, repository, path, and task. -2. Read the organization docs index. +2. Read the designated organization documentation source entry index. 3. Read the repository README and local instructions. 4. Apply path-specific instructions for files being changed. ``` From c29c48907f15422f78e2a41cd766781a2f608519 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 30 Aug 2026 13:45:13 +0200 Subject: [PATCH 12/19] Punctuate router source entry --- AGENTS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index 739bdac..4ff1726 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -8,7 +8,7 @@ Read in this order: 2. .github/CONTRIBUTING.md - how a change is made and reviewed 3. [MSXOrg/docs](https://github.com/MSXOrg/docs/) - this repository's documentation; entry file `src/docs/index.md`; published at - ; preferred clone `~/.msxorg/docs` + ; preferred clone `~/.msxorg/docs`. Use a CLI, the web, published documentation, or a refreshed local clone, whichever provides the newest accessible source. From 9ff4ca75315514707c26bd85199c038c2945afe7 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 30 Aug 2026 13:51:11 +0200 Subject: [PATCH 13/19] Align repository router with template --- AGENTS.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 4ff1726..e4442e1 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -4,13 +4,15 @@ Read nearest first and always use the newest version. Read in this order: -1. README.md - about the repo and what it contains -2. .github/CONTRIBUTING.md - how a change is made and reviewed -3. [MSXOrg/docs](https://github.com/MSXOrg/docs/) - this repository's - documentation; entry file `src/docs/index.md`; published at - ; preferred clone `~/.msxorg/docs`. +1. `README.md` — what this repository is and how it builds. +2. `.github/CONTRIBUTING.md` — how a change is made and reviewed here. +3. [MSXOrg/docs](https://github.com/MSXOrg/docs/) — this repository's + documentation and the organization standards; entry file + `src/docs/index.md`; published at ; preferred + clone `~/.msxorg/docs`. Use a CLI, the web, published documentation, or a refreshed local clone, whichever provides the newest accessible source. -Repository-local guidance may add nuance but does not override organization or inherited standards. +Repository-local guidance may add nuance but does not override organization or +inherited standards. From 382c321d4c52824d7d55d77963ea8b70b9a0be3b Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 30 Aug 2026 13:53:10 +0200 Subject: [PATCH 14/19] Restore the canonical agent template --- .../agentic-development/AGENTS.template.md | 31 +++++-------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/src/docs/Capabilities/agentic-development/AGENTS.template.md b/src/docs/Capabilities/agentic-development/AGENTS.template.md index c612347..7ba9c74 100644 --- a/src/docs/Capabilities/agentic-development/AGENTS.template.md +++ b/src/docs/Capabilities/agentic-development/AGENTS.template.md @@ -12,10 +12,11 @@ block into an `AGENTS.md` at the repository root. The router moves from the most specific guidance to the least specific: repository-local guidance first, initiative-specific guidance next, and the organization's central guidance last. -Each route names its source repository, entry file, published documentation, -and preferred local clone. An agent may use a CLI, the web, published -documentation, or a refreshed local clone. Clone and local configuration -mechanics belong to the runtime or development setup, not to this portable +Before using a linked repository, clone it locally, keep its configuration local +to that clone, and update it from its remote. +Agentic runtimes and local development may materialize that repository in any +context checkout they control. Clone, freshness, and local configuration +mechanics belong to that runtime or development setup, not to this portable router. Client-specific files such as `.claude/CLAUDE.md` and @@ -26,31 +27,15 @@ pointers to canonical documentation pages. ````markdown # AGENTS -Read nearest first and always use the newest version. - Read in this order: 1. `README.md` — what this repository is and how it builds. 2. `.github/CONTRIBUTING.md` — how a change is made and reviewed here. 3. `docs/index.md` — this repository's own documentation. -4. [MSXOrg/docs](https://github.com/MSXOrg/docs/) — organization standards; - entry file `src/docs/index.md`; published at ; - preferred clone `~/.msxorg/docs`. - -Use a CLI, the web, published documentation, or a refreshed local clone, -whichever provides the newest accessible source. +4. [MSXOrg/docs](https://github.com/MSXOrg/docs/) — the organization standards. -Repository-local guidance may add nuance but does not override organization or -inherited standards. +Clone each linked repository locally, keep its configuration local to that +clone, and update it before reading it. ```` - -A PSModule repository inserts this initiative route before `MSXOrg/docs`: - -```markdown -4. [PSModule/Process-PSModule](https://github.com/PSModule/Process-PSModule/) — - PSModule process and standards; entry file `docs/index.md`; published at - ; preferred clone - `~/.psmodule/process-psmodule`. -``` From 6e159731edcb11f8277fd8652280aea6ded24a4f Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 30 Aug 2026 13:58:08 +0200 Subject: [PATCH 15/19] Restore the repository agent router --- AGENTS.md | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index e4442e1..2dafcea 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,18 +1,7 @@ # AGENTS -Read nearest first and always use the newest version. - Read in this order: -1. `README.md` — what this repository is and how it builds. -2. `.github/CONTRIBUTING.md` — how a change is made and reviewed here. -3. [MSXOrg/docs](https://github.com/MSXOrg/docs/) — this repository's - documentation and the organization standards; entry file - `src/docs/index.md`; published at ; preferred - clone `~/.msxorg/docs`. - -Use a CLI, the web, published documentation, or a refreshed local clone, -whichever provides the newest accessible source. - -Repository-local guidance may add nuance but does not override organization or -inherited standards. +1. README.md - about the repo and what it contains +2. .github/CONTRIBUTING.md - how a change is made and reviewed +3. src/docs/index.md - the documentation this repository owns From ac02a701d4860b01a8f3ae5438b4b0bbfa5fb8d0 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 30 Aug 2026 13:59:04 +0200 Subject: [PATCH 16/19] Keep the agreed agent router standard --- .../agentic-development/conformance.md | 6 +- .../agentic-development/design.md | 117 ++++++++---------- .../Capabilities/agentic-development/index.md | 4 +- .../runtime-integration.md | 37 +++--- .../Capabilities/agentic-development/spec.md | 49 ++++---- src/docs/Capabilities/index.md | 2 +- 6 files changed, 98 insertions(+), 117 deletions(-) diff --git a/src/docs/Capabilities/agentic-development/conformance.md b/src/docs/Capabilities/agentic-development/conformance.md index a321b2b..00fe305 100644 --- a/src/docs/Capabilities/agentic-development/conformance.md +++ b/src/docs/Capabilities/agentic-development/conformance.md @@ -22,9 +22,9 @@ A conformant repository MUST provide all of the following. | **A router agent file** | The repository root holds a single agent instruction file, and it routes rather than instructs ([design](design.md#pointer-files)) | | **Reading order** | The router states the order in which context is read, from repository-local to organization-canonical | | **Client routes** | Every supported runtime's expected instruction path exists and resolves to the router, carrying no content of its own ([client behavior](design.md#client-behavior)) | -| **Canonical coordinates** | The router names each source repository, entry file, published documentation when available, and preferred clone | -| **Freshness** | The router requires the newest accessible source, and any local clone is synchronized before use ([context freshness](design.md#context-freshness)) | -| **Precedence** | The router states that repository-local guidance does not override organization or inherited standards | +| **Canonical coordinates** | The router names the organization's canonical documentation location, so context is reachable without prior knowledge | +| **Freshness** | Canonical context is synchronized at the start of every session, in every runtime ([context freshness](design.md#context-freshness)) | +| **Precedence** | The router states that local files never override a standard | The baseline is small on purpose. Every item is something an agent needs before it can find anything else; nothing on the list is a judgement about how the repository should be diff --git a/src/docs/Capabilities/agentic-development/design.md b/src/docs/Capabilities/agentic-development/design.md index f64ab17..4b7693b 100644 --- a/src/docs/Capabilities/agentic-development/design.md +++ b/src/docs/Capabilities/agentic-development/design.md @@ -5,7 +5,7 @@ description: How the agentic development framework is built — OKF documentatio # Agentic Development — Design -The behavior in the [spec](spec.md) is delivered by repository-addressable documentation sources, adopted by each product repository through thin pointer files. The design keeps project knowledge in one reviewed place and lets each agent runtime adapt without copying process knowledge. +The behavior in the [spec](spec.md) is delivered by an organization-level documentation repository, adopted by each product repository through thin pointer files. The design keeps project knowledge in one reviewed place and lets each agent runtime adapt without copying process knowledge. The repository name is not fixed; the organization identifies the source that owns its documentation. ## Organization anatomy @@ -13,26 +13,26 @@ The GitHub organization is the project boundary. The host distinguishes work fro ```text // - / # canonical knowledge base; changes through pull requests - / # product or component repository + docs/ # canonical knowledge base; changes through pull requests + / # product or component repository / ``` -Current project scopes identify these sources: +Current project scopes follow the same shape: -| Host | Organization | Documentation source | Entry file | Published documentation | Preferred clone | -| --- | --- | --- | --- | --- | --- | -| `github.com` | `MSXOrg` | `MSXOrg/docs` | `src/docs/index.md` | | `~/.msxorg/docs` | -| `github.com` | `PSModule` | `PSModule/Process-PSModule` | `docs/index.md` | | `~/.psmodule/process-psmodule` | -| `` | `` | Designated `/` | Declared by the router | Declared by the router | Declared by the router | +| Host | Organization | Docs | +| --- | --- | --- | +| `github.com` | `MSXOrg` | `MSXOrg/docs` | +| `github.com` | `PSModule` | `PSModule/Process-PSModule` | +| `` | `` | Designated `/` | -The last row is the general case. Repository identity remains stable whether an agent uses a CLI, the web, published documentation, or a refreshed local clone. +The last row is the general case: any adopting organization on any GitHub host — public or an enterprise instance — plugs into the same shape without changing the framework. ## Repository roles -### Documentation source +### `docs` -The designated documentation source is the canonical knowledge base. It owns: +The `docs` repository is the canonical knowledge base. It owns: - vision, principles, and ways of working; - coding standards and documentation standards; @@ -40,7 +40,7 @@ The designated documentation source is the canonical knowledge base. It owns: - project glossary and onboarding; - the canonical Workflow and its linked stage procedures. -Changes happen through pull requests because the source defines durable project intent. `MSXOrg/docs` owns cross-organization guidance. `PSModule/Process-PSModule` owns PSModule process and standards and inherits from `MSXOrg/docs`. +Changes to `docs` happen through pull requests because this repository defines durable project intent. ### Product repositories @@ -64,7 +64,7 @@ The repository owns only repository-specific nuance, and each kind has a file th ## OKF page model -Documentation sources use the [Open Knowledge Format](../../Dictionary/index.md#open-knowledge-format) style: Markdown with YAML frontmatter, one concept per page, paths as stable identity, and indexes as navigation maps. +The `docs` repository uses the [Open Knowledge Format](../../Dictionary/index.md#open-knowledge-format) style: Markdown with YAML frontmatter, one concept per page, paths as stable identity, and indexes as navigation maps. Minimum page frontmatter: @@ -102,14 +102,14 @@ flowchart TD start["Agent receives task"] --> policy["System and client policy"] policy --> user["User-global preferences"] user --> pointer["Read AGENTS.md pointer"] - pointer --> locate["Resolve documentation sources"] + pointer --> locate["Resolve host, org, and docs root"] locate --> host{"Which project scope?"} host -->|"github.com/MSXOrg"| msx["MSXOrg context"] host -->|"github.com/PSModule"| psmodule["PSModule context"] host -->|"any adopting org"| other["<host>/<org> context"] - msx --> refresh["Resolve newest source version
refresh local clones before use"] + msx --> refresh["Synchronize selected docs with Git
stop unless exactly synchronized"] psmodule --> refresh other --> refresh refresh --> repo["Read README, CONTRIBUTING,
and local docs"] @@ -131,42 +131,28 @@ Resolution is deterministic. If the active repository remote is `github.com/PSMo ## Pointer files -`AGENTS.md` is the cross-runtime router. It lists where to read, identifies each -source, and requires the newest accessible version without selecting an access -tool. It holds no detailed synchronization mechanics, build commands, -contribution mechanics, or standards. +`AGENTS.md` is the cross-runtime router. It lists where to read, in order, and +includes one instruction to prepare linked repositories before reading them. It +holds no detailed synchronization mechanics, build commands, contribution +mechanics, or standards. ```markdown # AGENTS -Read nearest first and always use the newest version. - Read in this order: 1. `README.md` — what this repository is and how it builds. 2. `.github/CONTRIBUTING.md` — how a change is made and reviewed here. 3. `docs/index.md` — this repository's own documentation. -4. [MSXOrg/docs](https://github.com/MSXOrg/docs/) — organization standards; - entry file `src/docs/index.md`; published at ; - preferred clone `~/.msxorg/docs`. - -Use a CLI, the web, published documentation, or a refreshed local clone, -whichever provides the newest accessible source. +4. [MSXOrg/docs](https://github.com/MSXOrg/docs/) — the organization standards. -Repository-local guidance may add nuance but does not override organization or -inherited standards. -``` - -A PSModule repository inserts its initiative source before `MSXOrg/docs`: +Clone each linked repository locally, keep its configuration local to that +clone, and update it before reading it. -```markdown -4. [PSModule/Process-PSModule](https://github.com/PSModule/Process-PSModule/) — - PSModule process and standards; entry file `docs/index.md`; published at - ; preferred clone - `~/.psmodule/process-psmodule`. +Read nearest first. A local file never overrides a standard. ``` -A router lists only destinations that apply to its repository. A repository with no documentation of its own drops that line; one that publishes the standards resolves local and organization documentation to the same source and drops the duplicate. The route does not require a particular client or access method. A local clone is usable only after its freshness gate succeeds. +A router lists the destinations that exist in that repository, written as the paths that repository actually uses — the ones above are an example, not a required layout. A repository with no documentation of its own drops that line; one that publishes the standards resolves steps 3 and 4 to the same tree and drops the duplicate. Writing a real path matters more than matching the example, because the router is read literally. The index trail is the default. A clear prompt can shortcut stage discovery: `Review this PR ` enters Review, `Make this issue ` enters Define, and `Implement ` enters Implement. These phrases are routing hints interpreted by [Workflow](../../Ways-of-Working/Workflow.md#find-the-current-stage), not commands with independent procedures. @@ -192,7 +178,7 @@ Path-scoped instruction files are reserved for local rules that cannot live cent ## Local workspace -A preferred local clone makes documentation context predictable: +A local Git clone makes central context predictable: ```text ~/.msxorg/ @@ -201,12 +187,11 @@ A preferred local clone makes documentation context predictable: process-psmodule/ # clean PSModule/Process-PSModule clone ``` -When an agent uses a local clone, it ensures the clone exists, fetches its -remote, and fast-forwards its default branch before reading. Each clone must be -clean, checked out on the remote default branch, and exactly equal to the -fetched remote head. A dirty, locally ahead, diverged, wrong-branch, or -unreachable clone stops local resolution; the agent does not use a stale copy. -Remote CLI, web, and published documentation remain valid current sources. +Before context is read, the agent ensures the clone exists, fetches its remote, +and fast-forwards its default branch. Each clone must be clean, checked out on +the remote default branch, and exactly equal to the fetched remote head. A +dirty, locally ahead, diverged, wrong-branch, or unreachable clone stops context +resolution; the agent does not use a possibly stale local copy. Each GitHub organization has its own organization-named workspace root, such as `~/.msxorg` for MSXOrg or `~/.psmodule` for PSModule. Repository agent files @@ -215,37 +200,37 @@ guidance defines how a context checkout is prepared and verified. ## Context freshness -The local freshness gate is only worth as much as the last time it ran. A clone +The freshness gate is only worth as much as the last time it ran. A clone synchronized once is current at that moment and progressively less so afterwards, and an agent reading a week-old clone reads a standard that has since changed while believing it is canonical. -When a runtime uses local clones, Git synchronization runs at the **start of -every session**, not once per machine. What differs between runtimes is where -the trigger hangs, never what it does: +So Git synchronization runs at the **start of every session**, not once per +machine. What differs between runtimes is where the trigger hangs, never what +it does: | Runtime shape | Lifecycle point | How context freshness is established | | --- | --- | --- | -| Local interactive agent | Session start | The agent resolves a current remote source or fetches and fast-forwards a preferred clone before the first turn. | -| Hosted or remote agent | Environment setup | Setup provides current documentation through a remote route or a freshly prepared clone. | +| Local interactive agent | Session start | The agent fetches and fast-forwards the context clone before the first turn. | +| Hosted or remote agent | Environment setup | The environment's setup steps clone or synchronize the context repository while the workspace is being prepared. | | Review-time agent | Pull request event | Instructions are read from the pull request's head branch, so freshness follows the branch under review rather than a local clone. | -| Batch or scheduled agent | Job start | The job resolves current documentation before acting; a scheduled run has no earlier lifecycle point to rely on. | +| Batch or scheduled agent | Job start | The job's first step clones or synchronizes the context repository; a scheduled run has no earlier lifecycle point to rely on. | -Each of these is one **declaration** of the same behavior: use the newest -accessible source. When that source is a local clone, the runtime ensures it is -clean, on the remote default branch, and exactly equal to the fetched head -before context is read. +Each of these is one **declaration** of the same behavior. The runtime ensures +the clone is clean, on the remote default branch, and exactly equal to the +fetched head before context is read. A runtime may use its own lifecycle hook, +or the agent may perform the Git check explicitly. The synchronization MUST be idempotent, because it runs far more often than it changes anything. A process that is expensive or noisy when everything is already current gets disabled, and a disabled process is worse than no process, because the workspace still appears synchronized. -Where a runtime uses local clones but offers no lifecycle point, Git -synchronization MUST be invoked explicitly before context is read. It MUST NOT -be skipped on the grounds that the workspace was synchronized recently; -"recently" is not a state the agent can observe, and the gate exists precisely -to replace that judgment with a check. +Where a runtime offers no lifecycle point at all, Git synchronization MUST be +invoked explicitly before context is read. It MUST NOT be skipped on the +grounds that the workspace was synchronized recently; "recently" is not a state +the agent can observe, and the gate exists precisely to replace that judgment +with a check. Each shape's obligations beyond context freshness — its entry file, tool declaration, and identity — are set out in [Runtime Integration](runtime-integration.md). @@ -269,7 +254,7 @@ Because Copilot code review reads the head branch, a pull request that changes ` | Failure | Design response | | --- | --- | | Repository does not identify its organization context | Infer from remote URL; ask when ambiguous. | -| A preferred clone is missing or cannot synchronize | Use a current remote route, or clone or repair it before reading locally. Never use the stale clone as fallback. | +| A docs clone is missing or cannot synchronize | Clone or repair it with Git, then retry. Stop context resolution until the canonical context repository passes the freshness gate. | | Pointer file duplicates central standards | Replace duplicated content with a route during review. A client file holds a pointer, not a copy. | | A skill, command, named agent, or instruction file defines a workflow stage | Delete the duplicate procedure and link to Workflow or its stage page. | | Two organizations are open in one workspace | Select by active repository; ask before cross-project changes. | @@ -278,10 +263,10 @@ Because Copilot code review reads the head branch, a pull request that changes ` ## Adoption path -1. Create or identify the organization's canonical documentation source. -2. Add the canonical Workflow and linked stage procedures to that source. +1. Create or identify the organization `docs` repository. +2. Add the canonical Workflow and linked stage procedures to `docs`. 3. Add the `AGENTS.md` router to each product repository, plus a route for every client that cannot read it. -4. Document source entry files, published documentation, and preferred clones; require Git synchronization only when a clone is used. +4. Document the canonical docs clone and require Git synchronization before use. 5. Review new work for pointer discipline: facts live once, links point to them. ## Where this connects diff --git a/src/docs/Capabilities/agentic-development/index.md b/src/docs/Capabilities/agentic-development/index.md index a33e4b3..b29e9ad 100644 --- a/src/docs/Capabilities/agentic-development/index.md +++ b/src/docs/Capabilities/agentic-development/index.md @@ -1,11 +1,11 @@ --- title: Agentic Development -description: The framework for repository-addressable organization documentation that gives agents project-specific standards and behavior. +description: The framework for org-scoped documentation that gives agents project-specific standards and behavior. --- # Agentic Development -The Agentic Development framework makes an organization the operating boundary for human and agent work. Each organization identifies the repository that owns its canonical knowledge; every product repository carries a short router that names the applicable sources and keeps its own nuance in the files a human already reads. +The Agentic Development framework makes an organization the operating boundary for human and agent work. Each organization identifies a canonical documentation repository; every product repository carries a short router that points to that source and keeps its own nuance in the files a human already reads. A repository adopts the framework by carrying a short router and the client routes that reach it, and by letting agents read outward — the repository's own files first, then the organization documentation, then the current task. The organization selects *which* context applies; the reading order decides what is read first. diff --git a/src/docs/Capabilities/agentic-development/runtime-integration.md b/src/docs/Capabilities/agentic-development/runtime-integration.md index 18f5bd3..ddfb9cd 100644 --- a/src/docs/Capabilities/agentic-development/runtime-integration.md +++ b/src/docs/Capabilities/agentic-development/runtime-integration.md @@ -19,7 +19,7 @@ MUST supply, and nothing else. | Obligation | What it means | Where it is defined | | --- | --- | --- | | **Entry file** | The instruction file the runtime reads first, which routes to the canonical router rather than restating it | [Pointer files](design.md#pointer-files) | -| **Lifecycle point** | The moment before the first turn where the runtime verifies that context is current | [Context freshness](design.md#context-freshness) | +| **Lifecycle point** | The moment before the first turn where the runtime verifies and synchronizes context | [Context freshness](design.md#context-freshness) | | **Tool declaration** | The shared tool server set, expressed in the runtime's own configuration format | [MCP Servers](mcp-servers.md#same-contract-different-declaration-syntax) | | **Identity** | The credential the runtime authenticates with, and the permissions that identity holds | [Permissions](#permissions-follow-the-identity-not-the-runtime) | @@ -45,9 +45,8 @@ Four shapes cover the field: | **Review-time** | Triggered by a platform event on a pull request | Reads instructions from the branch under review, not from a local clone | | **Scheduled** | On a timer, with no human present | No earlier lifecycle point exists, and no one is watching a failure | -The same freshness contract, router, and tool contract serve all four. What -changes is how the runtime reaches the named source and, when it uses a local -clone, where synchronization runs. +The same Git synchronization contract, the same router, and the same tool contract serve all +four. What changes is only where synchronization runs. ### Local interactive @@ -55,23 +54,21 @@ The durable workspace is the hazard. A local runtime is the only shape whose con survives between sessions, which means it is the only shape that can read a week-old standard while believing it is canonical. -When the runtime uses local clones, Git synchronization MUST attach to a -session-start lifecycle point in the runtime's own configuration and run before -the first turn rather than on first use of context. +So Git synchronization MUST attach to a session-start lifecycle point in the runtime's own +configuration, and it MUST run before the first turn rather than on first use of context. -Where the runtime offers no session-start point, local clones MUST be -synchronized explicitly before context is read. A runtime MAY instead use a -current remote CLI, web, or published-documentation route. +Where the runtime offers no session-start point, Git synchronization MUST be invoked explicitly +before context is read. ### Hosted A hosted runtime gets a fresh workspace per run, so staleness is not the risk — *absence* is. The environment either establishes context during setup or the agent works without it. -Context preparation therefore belongs in the environment's setup steps, and -failure MUST fail the run. The environment may clone and synchronize the source -or provide current remote access. An agent that starts successfully against -missing context produces work that looks finished and was never governed. +Git synchronization therefore belongs in the environment's setup steps, and setup failure MUST fail +the run. An agent that starts successfully against missing context produces work that looks +finished and was never governed, which is the most expensive failure in the set because it is +the one that reaches review looking normal. ### Review-time @@ -85,10 +82,10 @@ carefully as code, since they are live before merge. ### Scheduled -A scheduled runtime has no lifecycle point earlier than the job itself, so -context preparation is the job's first step. It also has no human to notice a -problem, which raises the bar on failure handling: a scheduled run MUST fail -loudly and MUST NOT proceed with partial context. +A scheduled runtime has no lifecycle point earlier than the job itself, so Git synchronization +is the job's first step. It also has no human to notice a problem, which raises the bar on +failure handling: a scheduled run MUST fail loudly and MUST NOT proceed with partial context, +because a silent partial run repeats on the schedule. ## Permissions follow the identity, not the runtime @@ -121,8 +118,8 @@ Adding a runtime is a documentation change plus four declarations, in this order 1. Identify its **shape** from the table above; the shape determines the lifecycle point. 2. Add its **entry file** as a route to the canonical router, carrying no process content. -3. Attach source freshness verification to its lifecycle point. For local - clones, preserve the clean, default-branch, fast-forward-only contract. +3. Attach Git synchronization to its lifecycle point, preserving the clean, default-branch, + fast-forward-only contract. 4. Declare the **shared tool set** in the runtime's native configuration format. 5. Record the **identity** it authenticates as and the permissions that identity holds. diff --git a/src/docs/Capabilities/agentic-development/spec.md b/src/docs/Capabilities/agentic-development/spec.md index 3d3f28b..bf2e272 100644 --- a/src/docs/Capabilities/agentic-development/spec.md +++ b/src/docs/Capabilities/agentic-development/spec.md @@ -9,17 +9,17 @@ description: Requirements for fresh, index-first agentic development through can An agent does useful work only when it knows which project it is serving, which standards apply, and what the team has already learned. That context MUST be project-scoped, durable, reviewable, and readable by humans and agents alike. The project boundary is the GitHub organization — `github.com/MSXOrg`, `github.com/PSModule`, and any other organization that adopts the framework, on any GitHub host. -Each organization identifies a canonical documentation source repository: +Each organization identifies a canonical documentation repository: -- The documentation source is the reviewed knowledge base: vision, standards, workflows, specs, designs, glossary, onboarding, and project-wide rules. It may be named `docs`, such as `MSXOrg/docs`, or be the repository that owns an initiative's process and standards, such as `PSModule/Process-PSModule`. +- The documentation repository owns the reviewed knowledge base: vision, standards, workflows, specs, designs, glossary, onboarding, and project-wide rules. It may be named `docs`, such as `MSXOrg/docs`, or be the repository that owns an initiative's process and standards, such as `PSModule/Process-PSModule`. -Product repositories do not copy that knowledge. They carry thin pointer files that identify the applicable documentation sources before acting. +Product repositories do not copy that knowledge. They carry thin pointer files that identify the organization context and direct agents to the relevant documentation repository before acting. ### Principles This framework rests on the [Principles](../../Ways-of-Working/Principles/index.md): -- **[Documentation lives close to the thing it documents](../../Ways-of-Working/Principles/Engineering-Practices.md#documentation-lives-close-to-the-thing-it-documents).** Organization-wide ways of working live in the organization's documentation source; repository-specific nuance lives in the repository. +- **[Documentation lives close to the thing it documents](../../Ways-of-Working/Principles/Engineering-Practices.md#documentation-lives-close-to-the-thing-it-documents).** Organization-wide ways of working live in the organization `docs` repository; repository-specific nuance lives in the repository. - **[Everything as Code](../../Ways-of-Working/Principles/Engineering-Practices.md#everything-as-code).** Standards are plain files in git. Changes are reviewed, diffed, and reverted like code. - **[Written once, referenced everywhere](../../Ways-of-Working/Principles/Software-Design.md#dry-with-judgment).** Agent instructions point to canonical docs rather than duplicating them. - **[AI-first development](../../Ways-of-Working/Principles/AI-First-Development.md).** Humans create durable context; agents consume that context and leave useful improvements behind. @@ -30,7 +30,7 @@ Applies to any organization that wants a shared project knowledge base for agent **In scope** -- Organization-level documentation source repositories. +- Organization-level `docs` repository. - Markdown documents with YAML frontmatter, following the [Open Knowledge Format](../../Dictionary/index.md#open-knowledge-format) model. - Thin repository pointer files: a required `AGENTS.md` router, and a route to it for every client that cannot read it. - Path-scoped rule files, reserved for local caveats that cannot live in repository or central documentation. @@ -52,42 +52,41 @@ Applies to any organization that wants a shared project knowledge base for agent ## Requirements - **Organization is the project boundary.** The framework MUST resolve project context from the Git host and organization before resolving repository-specific context. -- **Canonical documentation source.** Each adopting organization MUST identify the repository that owns its reviewed knowledge base. -- **Repository identity is authoritative.** A router MUST name each source as `/`. CLI, web, published-site, and refreshed-local-clone access are interchangeable delivery methods. -- **Predictable project context.** Repository-level agent instructions MUST identify each applicable public documentation source, its entry file, published documentation when available, and its preferred local clone. +- **Canonical documentation repository.** Each adopting organization MUST identify the repository that owns the reviewed knowledge base. +- **Predictable project context.** Repository-level agent instructions MUST identify the canonical documentation repository with a public repository pointer for each adopting organization. - **OKF-style documents.** Knowledge documents MUST be Markdown files with YAML frontmatter, one primary concept per page, and stable paths that act as identity. - **Small pages and indexes.** Documentation SHOULD prefer small pages, each folder SHOULD have an `index.md`, and indexes MUST let a human or agent navigate inward from the root. -- **Thin pointer files.** Product repositories MUST carry an `AGENTS.md` at the repository root that routes an agent from the repository's own files outward to organization and inherited ecosystem documentation. It MUST lead with `Read nearest first and always use the newest version.` and contain only the route list, source coordinates, access-neutral freshness instruction, and authority statement defined by the template. It MUST NOT duplicate standards, workflow stages, reusable process knowledge, detailed synchronization procedures, build commands, or contribution mechanics. -- **Freshness-first, index-first workflow discovery.** After every canonical source is resolved to its newest accessible version, a human or agent MUST be able to follow its entry index to the applicable workflow and current stage procedure. +- **Thin pointer files.** Product repositories MUST carry an `AGENTS.md` at the repository root that routes an agent from the repository's own files outward to the organization documentation and any inherited ecosystem documentation. It MUST be limited to that route list and the single context-preparation instruction defined by the template. It MUST NOT duplicate standards, workflow stages, or reusable process knowledge, and MUST NOT carry detailed synchronization procedures, build commands, or contribution mechanics. +- **Refresh-first, index-first workflow discovery.** After every canonical context repository passes the Git freshness gate, a human or agent MUST be able to follow the docs root index to Ways of Working, the canonical Workflow, and the procedure for the current stage. - **Stage resolution from work.** Agents MUST infer the current stage from the prompt and current artifacts. Explicit task language MAY shortcut to the matching stage, but the shortcut MUST resolve to the canonical documentation. - **One process source.** Skills, commands, named agents, and tool-specific instruction files MUST NOT redefine Workflow stages. A client convenience MAY link to a stage procedure and add only runtime mechanics. - **Segmentation before loading.** An agent MUST segment work by host, organization, repository, path, and task before loading project standards. The active repository context supplies the coordinates that make this possible; a per-repository router MUST NOT restate them. - **Client routes.** A runtime that cannot read `AGENTS.md` under its own filename MUST be given a route file — `.claude/CLAUDE.md`, `.github/copilot-instructions.md`, or the equivalent path for that runtime. A route file MUST contain only a pointer to `AGENTS.md` plus, at most, genuinely runtime-specific configuration that cannot be expressed as documentation. It MUST NOT restate standards, describe workflow behavior, or repeat the reading order. Duplication is a property of content rather than of filenames: a route holds nothing that can drift, so the number of route files is unconstrained while their contents are strictly limited. [Client behavior](design.md#client-behavior) names the exact set an MSX repository carries; an adopting organization MAY carry a different set for the runtimes it uses. - **Reading order and authority order are distinct.** An agent MUST read nearest context first, in the order the repository router defines. Precedence on conflict MUST run the opposite way: repository-local files MAY add nuance and narrow exceptions but MUST NOT override an organization or inherited ecosystem standard unless that standard permits a local exception. -- **Deterministic context resolution.** Agents MUST resolve context in layers: system and client policy, user preferences, the repository router, source freshness, repository context, path-scoped repository rules, organization documentation, inherited ecosystem documentation, then current task context. -- **Predictable local availability.** Preferred clones SHOULD use organization-addressable paths. MSXOrg uses `~/.msxorg/docs`; PSModule uses `~/.psmodule/process-psmodule`. -- **Fresh context before use.** Agents MUST use the newest accessible source version. Remote CLI, web, and published documentation MAY satisfy this directly. A local clone MUST be fetched and exactly synchronized with its remote default branch before its contents are read. Dirty, locally ahead, diverged, wrong-branch, or unreachable local clones MUST stop local resolution rather than become stale fallbacks. -- **Working checkouts are not context sources.** A local context source MUST be the preferred clone that passed the freshness gate. A working checkout cloned to change the documentation MUST NOT be used as canonical context unless it independently passes the same gate. -- **Synchronize local clones once per session, not once per machine.** When a runtime uses preferred local clones, the freshness gate MUST run at the start of every agent session. A clone synchronized at an earlier point MUST NOT be treated as current. +- **Deterministic context resolution.** Agents MUST resolve context in layers: system and client policy, user preferences, the repository router, the context-repository Git freshness gate, repository context, path-scoped repository rules, organization docs, any inherited ecosystem docs, then current task context. +- **Local-first availability.** The docs repository SHOULD be available locally in a predictable workspace so agents can read it without relying on search or web access. +- **Fresh context before use.** Every canonical context repository MUST be fetched and exactly synchronized with its remote default branch before its contents are read. Agents use Git directly; dirty, locally ahead, diverged, wrong-branch, or unreachable repositories MUST stop context resolution rather than fall back to stale content. +- **Working checkouts are not context sources.** Canonical context MUST be read from the documentation repository clone that passed the freshness gate. A working checkout of the `docs` repository — one cloned in order to change it rather than to be governed by it — MUST NOT be used as a context source, whatever path it occupies, because it sits outside the gate. +- **Synchronize once per session, not once per machine.** The freshness gate MUST run at the start of every agent session, in every runtime. A workspace that was synchronized at some earlier point MUST NOT be treated as current, because elapsed time is not a state the agent can observe. The agent MUST use Git to synchronize it or stop when the clone cannot be safely synchronized. - **One tool layer, declared per runtime.** Where agents use external tools, the set of tool servers MUST be defined once as a logical layer and each runtime MUST declare that same set in its own native configuration format. A runtime MUST NOT define tools of its own that other runtimes lack, because a capability available in one client and absent in another makes the documented procedure conditional on which client is running it. - **Named intents stay pointer-based.** A packaged shortcut for a recurring workflow — however a runtime names it — MUST resolve to the canonical documentation for that workflow and MUST contain only the runtime mechanics needed to get there. It MUST NOT restate the procedure, since a shortcut that carries a copy of the process becomes a second, silently diverging definition of it. - **Advice and authority are separate.** An automated agent MAY analyse work and publish its conclusion as advice on the artifact under review. It MUST NOT be the thing that decides: it MUST NOT overwrite a human's decision, MUST NOT re-apply a decision a human has changed, and MUST NOT commit to the branch it is advising on. Its output is an input to the review, not a substitute for it. - **Coordination happens on durable artifacts.** Where agents and humans coordinate, they MUST do so through the platform's own artifacts — issues, labels, and pull requests — rather than through a channel that leaves no trace in the repository. Intent MUST be separable from implementation: the issue states *what* is wanted and *why*, and the pull request proposes *how*, so that a rejected implementation does not discard the intent. -- **Reviewed knowledge changes.** Changes to a canonical documentation source MUST happen through pull requests. +- **Reviewed knowledge changes.** Changes to the `docs` repository MUST happen through pull requests. - **No cross-project bleed.** An agent working in one organization MUST NOT apply another organization's standards unless the current task explicitly asks for cross-organization work. ## Success criteria -- An agent working in `github.com/PSModule/` resolves `github.com/PSModule/Process-PSModule` and inherited `github.com/MSXOrg/docs`. +- An agent working in `github.com/PSModule/` reads `github.com/PSModule/Process-PSModule` and inherited `github.com/MSXOrg/docs`. - An agent working in `github.com/MSXOrg/` resolves `github.com/MSXOrg/docs` as the canonical project context. -- An agent working in `//` for any adopting organization resolves the documentation sources declared by its router, with no change to the framework. +- An agent working in `//` for any adopting organization resolves its designated documentation repository as the canonical project context, with no change to the framework. - A new product repository can adopt the framework by adding a router and the client routes that reach it, without copying standards pages. -- An agent reads the repository's own `README.md` and `.github/CONTRIBUTING.md` before it reads an organization standard, and still applies the organization standard when the two disagree. +- An agent reads the repository's own README and CONTRIBUTING before it reads an organization standard, and still applies the organization standard when the two disagree. - A human or agent can follow `docs/index.md` → Ways of Working → Workflow → the current stage procedure without knowing a file path in advance. - A prompt such as `Review this PR ` reaches the Review procedure directly, while `Make this issue ` reaches Define, without a parallel process definition. -- A dirty, locally ahead, diverged, wrong-branch, or unreachable preferred clone stops local discovery before any context index is read. -- A reader can distinguish a current preferred clone from a working checkout or stale clone before trusting it. -- Updating a standard in its source repository changes the canonical guidance without editing every repository. +- A missing, dirty, locally ahead, diverged, wrong-branch, or unreachable canonical context repository stops discovery before any context index is read. +- A working checkout of a `docs` repository present on disk is not read as canonical context, and a reader can tell a current checkout from a stale one before trusting either. +- Updating a standard in `docs` changes the canonical guidance without editing every repository. ## Context resolution contract @@ -95,11 +94,11 @@ The framework uses this normative reading order: 1. **System and client policy** — non-project instructions imposed by the agent runtime. 2. **User-global preferences** — the human operator's baseline style and risk posture. -3. **Repository router** — `AGENTS.md` identifies the applicable source repositories and the order in which they are read. -4. **Freshness gate** — use the newest accessible source; when using a local clone, fetch it and stop local resolution unless its clean default-branch checkout exactly matches the remote head. +3. **Repository router** — `AGENTS.md` identifies the host, organization, and the context sources below, in the order they are read. +4. **Freshness gate** — fetch every canonical context repository and stop unless each clean default-branch checkout exactly matches its remote head. 5. **Repository context** — README, CONTRIBUTING, local docs, and narrow repository exceptions. 6. **Path-scoped repository rules** — local rules that apply to the files being read, generated, reviewed, or edited. -7. **Organization documentation** — the designated documentation source for the resolved organization: start at its declared entry file, resolve the applicable workflow and current stage, then load relevant standards, specs, and designs. +7. **Organization documentation** — the designated documentation repository for the resolved organization: start at its entry index, resolve the current stage, then load the relevant standards, specs, and designs. 8. **Inherited ecosystem documentation** — where the organization inherits from a broader standard set, the layer it inherits from. 9. **Current task context** — issue, pull request, prompt, branch, diff, diagnostics, terminal output, and open files; use these artifacts to re-evaluate the stage after each handoff. diff --git a/src/docs/Capabilities/index.md b/src/docs/Capabilities/index.md index 296b38d..b3b57f5 100644 --- a/src/docs/Capabilities/index.md +++ b/src/docs/Capabilities/index.md @@ -28,7 +28,7 @@ the same spec-and-design shape as any other capability. | [Deployment](deployment/index.md) | How a change to managed resources is approved together with its effect and deployed exactly as approved — one spec, and one design for each combination of deploying a service provider from a CI/CD platform. | | [VS Code Extension Framework](vscode-extension-framework/index.md) | How a VS Code extension is built, tested, versioned, packaged, and published — one GitHub-native pipeline, opt-in from a template and a single settings file. | | [PowerShell on GitHub](powershell-on-github/index.md) | How we make GitHub a first-class platform for PowerShell through reusable modules, actions, and capability gaps we close over time. | -| [Agentic Development](agentic-development/index.md) | The framework for repository-addressable organization documentation that gives agents project-specific standards and behavior. | +| [Agentic Development](agentic-development/index.md) | The framework for org-scoped documentation that gives agents project-specific standards and behavior. | From f727a81ae4e49fd41ea128a2a91166aa8fb2182e Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 30 Aug 2026 14:03:55 +0200 Subject: [PATCH 17/19] Clarify documentation repository coordinates --- src/docs/Capabilities/agentic-development/design.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/docs/Capabilities/agentic-development/design.md b/src/docs/Capabilities/agentic-development/design.md index 4b7693b..877e084 100644 --- a/src/docs/Capabilities/agentic-development/design.md +++ b/src/docs/Capabilities/agentic-development/design.md @@ -20,11 +20,11 @@ The GitHub organization is the project boundary. The host distinguishes work fro Current project scopes follow the same shape: -| Host | Organization | Docs | +| Host | Organization | Canonical documentation repository | | --- | --- | --- | | `github.com` | `MSXOrg` | `MSXOrg/docs` | | `github.com` | `PSModule` | `PSModule/Process-PSModule` | -| `` | `` | Designated `/` | +| `` | `` | Designated `/` | The last row is the general case: any adopting organization on any GitHub host — public or an enterprise instance — plugs into the same shape without changing the framework. From 55a0b3067552c499271815811b6125d062d6162a Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 30 Aug 2026 14:08:20 +0200 Subject: [PATCH 18/19] Remove documentation repository name assumptions --- .../Capabilities/agentic-development/spec.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/docs/Capabilities/agentic-development/spec.md b/src/docs/Capabilities/agentic-development/spec.md index bf2e272..ef948e6 100644 --- a/src/docs/Capabilities/agentic-development/spec.md +++ b/src/docs/Capabilities/agentic-development/spec.md @@ -30,7 +30,7 @@ Applies to any organization that wants a shared project knowledge base for agent **In scope** -- Organization-level `docs` repository. +- Organization-level canonical documentation repository. - Markdown documents with YAML frontmatter, following the [Open Knowledge Format](../../Dictionary/index.md#open-knowledge-format) model. - Thin repository pointer files: a required `AGENTS.md` router, and a route to it for every client that cannot read it. - Path-scoped rule files, reserved for local caveats that cannot live in repository or central documentation. @@ -57,22 +57,22 @@ Applies to any organization that wants a shared project knowledge base for agent - **OKF-style documents.** Knowledge documents MUST be Markdown files with YAML frontmatter, one primary concept per page, and stable paths that act as identity. - **Small pages and indexes.** Documentation SHOULD prefer small pages, each folder SHOULD have an `index.md`, and indexes MUST let a human or agent navigate inward from the root. - **Thin pointer files.** Product repositories MUST carry an `AGENTS.md` at the repository root that routes an agent from the repository's own files outward to the organization documentation and any inherited ecosystem documentation. It MUST be limited to that route list and the single context-preparation instruction defined by the template. It MUST NOT duplicate standards, workflow stages, or reusable process knowledge, and MUST NOT carry detailed synchronization procedures, build commands, or contribution mechanics. -- **Refresh-first, index-first workflow discovery.** After every canonical context repository passes the Git freshness gate, a human or agent MUST be able to follow the docs root index to Ways of Working, the canonical Workflow, and the procedure for the current stage. +- **Refresh-first, index-first workflow discovery.** After every canonical context repository passes the Git freshness gate, a human or agent MUST be able to follow its entry index to the canonical Workflow and the procedure for the current stage. - **Stage resolution from work.** Agents MUST infer the current stage from the prompt and current artifacts. Explicit task language MAY shortcut to the matching stage, but the shortcut MUST resolve to the canonical documentation. - **One process source.** Skills, commands, named agents, and tool-specific instruction files MUST NOT redefine Workflow stages. A client convenience MAY link to a stage procedure and add only runtime mechanics. - **Segmentation before loading.** An agent MUST segment work by host, organization, repository, path, and task before loading project standards. The active repository context supplies the coordinates that make this possible; a per-repository router MUST NOT restate them. - **Client routes.** A runtime that cannot read `AGENTS.md` under its own filename MUST be given a route file — `.claude/CLAUDE.md`, `.github/copilot-instructions.md`, or the equivalent path for that runtime. A route file MUST contain only a pointer to `AGENTS.md` plus, at most, genuinely runtime-specific configuration that cannot be expressed as documentation. It MUST NOT restate standards, describe workflow behavior, or repeat the reading order. Duplication is a property of content rather than of filenames: a route holds nothing that can drift, so the number of route files is unconstrained while their contents are strictly limited. [Client behavior](design.md#client-behavior) names the exact set an MSX repository carries; an adopting organization MAY carry a different set for the runtimes it uses. - **Reading order and authority order are distinct.** An agent MUST read nearest context first, in the order the repository router defines. Precedence on conflict MUST run the opposite way: repository-local files MAY add nuance and narrow exceptions but MUST NOT override an organization or inherited ecosystem standard unless that standard permits a local exception. - **Deterministic context resolution.** Agents MUST resolve context in layers: system and client policy, user preferences, the repository router, the context-repository Git freshness gate, repository context, path-scoped repository rules, organization docs, any inherited ecosystem docs, then current task context. -- **Local-first availability.** The docs repository SHOULD be available locally in a predictable workspace so agents can read it without relying on search or web access. +- **Local-first availability.** The canonical documentation repository SHOULD be available locally in a predictable workspace so agents can read it without relying on search or web access. - **Fresh context before use.** Every canonical context repository MUST be fetched and exactly synchronized with its remote default branch before its contents are read. Agents use Git directly; dirty, locally ahead, diverged, wrong-branch, or unreachable repositories MUST stop context resolution rather than fall back to stale content. -- **Working checkouts are not context sources.** Canonical context MUST be read from the documentation repository clone that passed the freshness gate. A working checkout of the `docs` repository — one cloned in order to change it rather than to be governed by it — MUST NOT be used as a context source, whatever path it occupies, because it sits outside the gate. +- **Working checkouts are not context sources.** Canonical context MUST be read from the documentation repository clone that passed the freshness gate. A working checkout cloned to change that repository rather than to be governed by it MUST NOT be used as a context source, whatever path it occupies, because it sits outside the gate. - **Synchronize once per session, not once per machine.** The freshness gate MUST run at the start of every agent session, in every runtime. A workspace that was synchronized at some earlier point MUST NOT be treated as current, because elapsed time is not a state the agent can observe. The agent MUST use Git to synchronize it or stop when the clone cannot be safely synchronized. - **One tool layer, declared per runtime.** Where agents use external tools, the set of tool servers MUST be defined once as a logical layer and each runtime MUST declare that same set in its own native configuration format. A runtime MUST NOT define tools of its own that other runtimes lack, because a capability available in one client and absent in another makes the documented procedure conditional on which client is running it. - **Named intents stay pointer-based.** A packaged shortcut for a recurring workflow — however a runtime names it — MUST resolve to the canonical documentation for that workflow and MUST contain only the runtime mechanics needed to get there. It MUST NOT restate the procedure, since a shortcut that carries a copy of the process becomes a second, silently diverging definition of it. - **Advice and authority are separate.** An automated agent MAY analyse work and publish its conclusion as advice on the artifact under review. It MUST NOT be the thing that decides: it MUST NOT overwrite a human's decision, MUST NOT re-apply a decision a human has changed, and MUST NOT commit to the branch it is advising on. Its output is an input to the review, not a substitute for it. - **Coordination happens on durable artifacts.** Where agents and humans coordinate, they MUST do so through the platform's own artifacts — issues, labels, and pull requests — rather than through a channel that leaves no trace in the repository. Intent MUST be separable from implementation: the issue states *what* is wanted and *why*, and the pull request proposes *how*, so that a rejected implementation does not discard the intent. -- **Reviewed knowledge changes.** Changes to the `docs` repository MUST happen through pull requests. +- **Reviewed knowledge changes.** Changes to the canonical documentation repository MUST happen through pull requests. - **No cross-project bleed.** An agent working in one organization MUST NOT apply another organization's standards unless the current task explicitly asks for cross-organization work. ## Success criteria @@ -82,11 +82,11 @@ Applies to any organization that wants a shared project knowledge base for agent - An agent working in `//` for any adopting organization resolves its designated documentation repository as the canonical project context, with no change to the framework. - A new product repository can adopt the framework by adding a router and the client routes that reach it, without copying standards pages. - An agent reads the repository's own README and CONTRIBUTING before it reads an organization standard, and still applies the organization standard when the two disagree. -- A human or agent can follow `docs/index.md` → Ways of Working → Workflow → the current stage procedure without knowing a file path in advance. +- A human or agent can follow the declared entry index to the applicable Workflow and current stage procedure. - A prompt such as `Review this PR ` reaches the Review procedure directly, while `Make this issue ` reaches Define, without a parallel process definition. - A missing, dirty, locally ahead, diverged, wrong-branch, or unreachable canonical context repository stops discovery before any context index is read. -- A working checkout of a `docs` repository present on disk is not read as canonical context, and a reader can tell a current checkout from a stale one before trusting either. -- Updating a standard in `docs` changes the canonical guidance without editing every repository. +- A working checkout of a canonical documentation repository present on disk is not read as context, and a reader can tell a current context clone from a stale one before trusting either. +- Updating a standard in its canonical documentation repository changes the guidance without editing every product repository. ## Context resolution contract From 2624ad22edd1262e403921c04f25b1c35685d37a Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 30 Aug 2026 14:33:32 +0200 Subject: [PATCH 19/19] Leave documentation clone placement to runtimes --- .../Capabilities/agentic-development/design.md | 18 ++++++------------ src/docs/Ways-of-Working/Git-Worktrees.md | 6 +++--- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/src/docs/Capabilities/agentic-development/design.md b/src/docs/Capabilities/agentic-development/design.md index 877e084..322a338 100644 --- a/src/docs/Capabilities/agentic-development/design.md +++ b/src/docs/Capabilities/agentic-development/design.md @@ -178,14 +178,9 @@ Path-scoped instruction files are reserved for local rules that cannot live cent ## Local workspace -A local Git clone makes central context predictable: - -```text -~/.msxorg/ - docs/ # clean MSXOrg/docs clone -~/.psmodule/ - process-psmodule/ # clean PSModule/Process-PSModule clone -``` +A runtime or development setup may materialize a documentation repository in +any context checkout it controls. The framework does not prescribe that +checkout's filesystem location. Before context is read, the agent ensures the clone exists, fetches its remote, and fast-forwards its default branch. Each clone must be clean, checked out on @@ -193,10 +188,9 @@ the remote default branch, and exactly equal to the fetched remote head. A dirty, locally ahead, diverged, wrong-branch, or unreachable clone stops context resolution; the agent does not use a possibly stale local copy. -Each GitHub organization has its own organization-named workspace root, such as -`~/.msxorg` for MSXOrg or `~/.psmodule` for PSModule. Repository agent files -retain public organization documentation destinations; runtime and development -guidance defines how a context checkout is prepared and verified. +Repository agent files retain public organization documentation destinations; +runtime and development guidance defines how a context checkout is prepared and +verified. ## Context freshness diff --git a/src/docs/Ways-of-Working/Git-Worktrees.md b/src/docs/Ways-of-Working/Git-Worktrees.md index 3bd0409..5b998c5 100644 --- a/src/docs/Ways-of-Working/Git-Worktrees.md +++ b/src/docs/Ways-of-Working/Git-Worktrees.md @@ -42,9 +42,9 @@ In a single ordinary clone the opposite is forced: one branch checked out at a t - **`/`** — the canonical default-branch worktree. Kept clean and exactly synchronized for reading, diffing, and comparisons. Never directly committed to. - **`-/`** — one worktree folder per repository-delivery Task or Bug in flight, named by issue number and a short slug. The folder is a concise local path; its branch uses the required `/-` name, so the two names do not need to match. -Canonical documentation context is a normal Git clone, such as -`~/.msxorg/docs` or `~/.psmodule/process-psmodule`, and is not part of this worktree -topology. The bare-clone layout applies to delivery repositories only. +Canonical documentation context uses a normal Git clone at a location chosen by +the runtime or development setup and is not part of this worktree topology. The +bare-clone layout applies to delivery repositories only. ## Remotes