Integrate divine manifestation and interception
This commit is contained in:
parent
c43dd5695f
commit
2eb74c574a
72 changed files with 5674 additions and 197 deletions
211
scripts/lore/check-phase-boundary-intake.ps1
Normal file
211
scripts/lore/check-phase-boundary-intake.ps1
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateSet('review', 'closure')]
|
||||
[string]$Boundary,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$PacketPath,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$PassPath,
|
||||
|
||||
[string]$RepositoryRoot
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
if (-not $RepositoryRoot) {
|
||||
$RepositoryRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot)
|
||||
}
|
||||
$repoFull = [System.IO.Path]::GetFullPath($RepositoryRoot).TrimEnd('\', '/')
|
||||
if (-not (Test-Path -LiteralPath $repoFull -PathType Container)) {
|
||||
throw "Repository root not found: $repoFull"
|
||||
}
|
||||
|
||||
function Resolve-RepositoryFile {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$Path,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$Label
|
||||
)
|
||||
|
||||
$candidate = $Path
|
||||
if (-not [System.IO.Path]::IsPathRooted($candidate)) {
|
||||
$candidate = Join-Path $repoFull $candidate
|
||||
}
|
||||
$full = [System.IO.Path]::GetFullPath($candidate)
|
||||
if (-not $full.StartsWith($repoFull + [System.IO.Path]::DirectorySeparatorChar, [System.StringComparison]::OrdinalIgnoreCase)) {
|
||||
throw "$Label must remain inside the repository root: $full"
|
||||
}
|
||||
if (-not (Test-Path -LiteralPath $full -PathType Leaf)) {
|
||||
throw "$Label not found: $full"
|
||||
}
|
||||
return $full
|
||||
}
|
||||
|
||||
function Invoke-RepositoryGit {
|
||||
param([Parameter(Mandatory = $true)][string[]]$Arguments)
|
||||
|
||||
$output = & git -C $repoFull -c core.quotepath=false @Arguments 2>&1
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "git $($Arguments -join ' ') failed:`n$($output -join "`n")"
|
||||
}
|
||||
return @($output)
|
||||
}
|
||||
|
||||
function Normalize-RepositoryPath {
|
||||
param([Parameter(Mandatory = $true)][string]$Path)
|
||||
|
||||
$normalized = $Path.Trim().Trim('`').Replace('\', '/')
|
||||
while ($normalized.StartsWith('./', [System.StringComparison]::Ordinal)) {
|
||||
$normalized = $normalized.Substring(2)
|
||||
}
|
||||
return $normalized
|
||||
}
|
||||
|
||||
function Get-FrontMatter {
|
||||
param([Parameter(Mandatory = $true)][string]$Text)
|
||||
|
||||
$match = [regex]::Match($Text, '\A---\r?\n(?<body>.*?)\r?\n---(?:\r?\n|\z)', [System.Text.RegularExpressions.RegexOptions]::Singleline)
|
||||
if (-not $match.Success) {
|
||||
return ''
|
||||
}
|
||||
return $match.Groups['body'].Value
|
||||
}
|
||||
|
||||
function Test-IsIntakeNote {
|
||||
param([Parameter(Mandatory = $true)][string]$RepositoryPath)
|
||||
|
||||
$full = Join-Path $repoFull ($RepositoryPath.Replace('/', [System.IO.Path]::DirectorySeparatorChar))
|
||||
if (-not (Test-Path -LiteralPath $full -PathType Leaf)) {
|
||||
return $false
|
||||
}
|
||||
|
||||
$stem = [System.IO.Path]::GetFileNameWithoutExtension($full)
|
||||
if ($stem -match '(?i)(?:^|[-_ ])(?:proposal|handoff)(?:$|[-_ ])') {
|
||||
return $true
|
||||
}
|
||||
|
||||
$frontMatter = Get-FrontMatter -Text (Get-Content -LiteralPath $full -Raw -Encoding utf8)
|
||||
if (-not $frontMatter) {
|
||||
return $false
|
||||
}
|
||||
|
||||
return (
|
||||
$frontMatter -match '(?im)^\s*status:\s*(?:proposal|handoff|adopted-candidate)\s*(?:#.*)?$' -or
|
||||
$frontMatter -match '(?im)^\s*(?:type|owns):[^\r\n]*(?:proposal|handoff)' -or
|
||||
$frontMatter -match '(?im)^\s*-\s*(?:proposal|handoff)\s*$'
|
||||
)
|
||||
}
|
||||
|
||||
$packetFull = Resolve-RepositoryFile -Path $PacketPath -Label 'Packet'
|
||||
$passFull = Resolve-RepositoryFile -Path $PassPath -Label 'Pass record'
|
||||
$packetText = Get-Content -LiteralPath $packetFull -Raw -Encoding utf8
|
||||
$passText = Get-Content -LiteralPath $passFull -Raw -Encoding utf8
|
||||
|
||||
$baseMatch = [regex]::Match($passText, '(?im)^intake_base_commit:\s*([0-9a-f]{40})\s*$')
|
||||
if (-not $baseMatch.Success) {
|
||||
throw 'Pass record must name a full 40-character intake_base_commit in its frontmatter'
|
||||
}
|
||||
$baseCommit = $baseMatch.Groups[1].Value.ToLowerInvariant()
|
||||
Invoke-RepositoryGit -Arguments @('rev-parse', '--verify', "$baseCommit^{commit}") | Out-Null
|
||||
|
||||
$manifest = [System.Collections.Generic.Dictionary[string, string]]::new([System.StringComparer]::OrdinalIgnoreCase)
|
||||
$manifestMatches = [regex]::Matches($packetText, '(?m)^(?<hash>[0-9a-fA-F]{40})[ \t]{2,}(?<path>.+?\.md)[ \t]*\r?$')
|
||||
foreach ($match in $manifestMatches) {
|
||||
$path = Normalize-RepositoryPath -Path $match.Groups['path'].Value
|
||||
$hash = $match.Groups['hash'].Value.ToLowerInvariant()
|
||||
if ($manifest.ContainsKey($path) -and $manifest[$path] -ne $hash) {
|
||||
throw "Packet contains conflicting hashes for $path"
|
||||
}
|
||||
$manifest[$path] = $hash
|
||||
}
|
||||
if ($manifest.Count -eq 0) {
|
||||
throw 'Packet must contain an exact raw SHA-1 Markdown manifest using: <40-hex-hash><two spaces><repository-relative-path>'
|
||||
}
|
||||
|
||||
$dispositions = [System.Collections.Generic.Dictionary[string, object]]::new([System.StringComparer]::OrdinalIgnoreCase)
|
||||
$intakeSection = [regex]::Match($passText, '(?ms)^## Phase-boundary intake\s*\r?\n(?<body>.*?)(?=^##\s|\z)')
|
||||
if ($intakeSection.Success) {
|
||||
foreach ($line in ($intakeSection.Groups['body'].Value -split '\r?\n')) {
|
||||
if (-not $line.Trim().StartsWith('|')) {
|
||||
continue
|
||||
}
|
||||
$cells = $line.Split('|')
|
||||
if ($cells.Count -lt 5) {
|
||||
continue
|
||||
}
|
||||
$pathCell = $cells[1].Trim().Trim('`')
|
||||
$disposition = $cells[2].Trim().ToLowerInvariant()
|
||||
$reason = $cells[3].Trim()
|
||||
if (-not $pathCell.EndsWith('.md', [System.StringComparison]::OrdinalIgnoreCase)) {
|
||||
continue
|
||||
}
|
||||
$path = Normalize-RepositoryPath -Path $pathCell
|
||||
$dispositions[$path] = [pscustomobject]@{
|
||||
Disposition = $disposition
|
||||
Reason = $reason
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$changedPaths = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::OrdinalIgnoreCase)
|
||||
$gitQueries = @(
|
||||
@('diff', '--name-only', '--diff-filter=ACMR', "$baseCommit..HEAD"),
|
||||
@('diff', '--cached', '--name-only', '--diff-filter=ACMR'),
|
||||
@('diff', '--name-only', '--diff-filter=ACMR'),
|
||||
@('ls-files', '--others', '--exclude-standard')
|
||||
)
|
||||
foreach ($query in $gitQueries) {
|
||||
foreach ($line in (Invoke-RepositoryGit -Arguments $query)) {
|
||||
$path = Normalize-RepositoryPath -Path ([string]$line)
|
||||
if ($path.EndsWith('.md', [System.StringComparison]::OrdinalIgnoreCase)) {
|
||||
[void]$changedPaths.Add($path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$intakeNotes = @($changedPaths | Where-Object { Test-IsIntakeNote -RepositoryPath $_ } | Sort-Object)
|
||||
$errors = @()
|
||||
$results = @()
|
||||
|
||||
foreach ($path in $intakeNotes) {
|
||||
if ($manifest.ContainsKey($path)) {
|
||||
$full = Join-Path $repoFull ($path.Replace('/', [System.IO.Path]::DirectorySeparatorChar))
|
||||
$actualHash = (Get-FileHash -LiteralPath $full -Algorithm SHA1).Hash.ToLowerInvariant()
|
||||
if ($actualHash -ne $manifest[$path]) {
|
||||
$errors += "$path is named in the packet but its current raw SHA-1 differs from the frozen manifest"
|
||||
}
|
||||
else {
|
||||
$results += "packet: $path"
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if (-not $dispositions.ContainsKey($path)) {
|
||||
$errors += "$path is a changed proposal or handoff note outside the frozen packet and has no intake disposition"
|
||||
continue
|
||||
}
|
||||
|
||||
$entry = $dispositions[$path]
|
||||
if ($entry.Disposition -notin @('defer', 'reject')) {
|
||||
$errors += "$path uses unsupported disposition '$($entry.Disposition)'; use defer or reject for a note outside the packet"
|
||||
continue
|
||||
}
|
||||
if ([string]::IsNullOrWhiteSpace($entry.Reason) -or $entry.Reason -match '^(?:replace-me|tbd|todo|-)$') {
|
||||
$errors += "$path requires a concrete reason or destination for disposition '$($entry.Disposition)'"
|
||||
continue
|
||||
}
|
||||
$results += "$($entry.Disposition): $path — $($entry.Reason)"
|
||||
}
|
||||
|
||||
if ($errors.Count -gt 0) {
|
||||
throw "Phase-boundary intake failed before $Boundary`:`n- $($errors -join "`n- ")"
|
||||
}
|
||||
|
||||
Write-Output "Phase-boundary intake passed before ${Boundary}: $($intakeNotes.Count) changed proposal/handoff note(s) examined since $baseCommit."
|
||||
foreach ($result in $results) {
|
||||
Write-Output "- $result"
|
||||
}
|
||||
|
|
@ -140,7 +140,9 @@ try {
|
|||
throw "Publication checker failed to reject a nested spoiler directory"
|
||||
}
|
||||
|
||||
Write-Output "Lore tool tests passed, including broken-link, broken-anchor, escaped-link, stale-output, exposed-vault-directory, spoiler-session, and publication-boundary negative checks."
|
||||
& (Join-Path $PSScriptRoot "test-phase-boundary-intake.ps1")
|
||||
|
||||
Write-Output "Lore tool tests passed, including phase-boundary intake, broken-link, broken-anchor, escaped-link, stale-output, exposed-vault-directory, spoiler-session, and publication-boundary negative checks."
|
||||
}
|
||||
finally {
|
||||
$resolvedFixture = [System.IO.Path]::GetFullPath($fixtureFull)
|
||||
|
|
|
|||
127
scripts/lore/test-phase-boundary-intake.ps1
Normal file
127
scripts/lore/test-phase-boundary-intake.ps1
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$tempBase = [System.IO.Path]::GetFullPath([System.IO.Path]::GetTempPath()).TrimEnd('\', '/')
|
||||
$fixture = Join-Path $tempBase ("kalsa-phase-intake-" + [guid]::NewGuid().ToString())
|
||||
New-Item -ItemType Directory -Path $fixture | Out-Null
|
||||
$fixtureFull = [System.IO.Path]::GetFullPath($fixture)
|
||||
if (-not $fixtureFull.StartsWith($tempBase + [System.IO.Path]::DirectorySeparatorChar, [System.StringComparison]::OrdinalIgnoreCase)) {
|
||||
throw 'Refusing to create phase-intake fixture outside the system temporary directory'
|
||||
}
|
||||
|
||||
function Invoke-FixtureGit {
|
||||
param([Parameter(Mandatory = $true)][string[]]$Arguments)
|
||||
|
||||
$output = & git -C $fixtureFull @Arguments 2>&1
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Fixture git command failed: git $($Arguments -join ' ')`n$($output -join "`n")"
|
||||
}
|
||||
return @($output)
|
||||
}
|
||||
|
||||
function Assert-CheckerFails {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)][string]$Boundary,
|
||||
[Parameter(Mandatory = $true)][string]$Message
|
||||
)
|
||||
|
||||
$caught = $false
|
||||
try {
|
||||
& (Join-Path $PSScriptRoot 'check-phase-boundary-intake.ps1') `
|
||||
-Boundary $Boundary `
|
||||
-PacketPath 'packet.md' `
|
||||
-PassPath 'pass.md' `
|
||||
-RepositoryRoot $fixtureFull | Out-Null
|
||||
}
|
||||
catch {
|
||||
$caught = $true
|
||||
}
|
||||
if (-not $caught) {
|
||||
throw $Message
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
New-Item -ItemType Directory -Path (Join-Path $fixtureFull 'Kalsa\Spoilers\Reference') -Force | Out-Null
|
||||
Set-Content -LiteralPath (Join-Path $fixtureFull 'Owner.md') -Encoding utf8 -Value "# Owner`n"
|
||||
Invoke-FixtureGit -Arguments @('init', '-b', 'main') | Out-Null
|
||||
Invoke-FixtureGit -Arguments @('add', '--', 'Owner.md') | Out-Null
|
||||
Invoke-FixtureGit -Arguments @('-c', 'user.name=Kalsa Tests', '-c', 'user.email=kalsa-tests@example.invalid', 'commit', '-m', 'Fixture baseline') | Out-Null
|
||||
$baseCommit = ([string](Invoke-FixtureGit -Arguments @('rev-parse', 'HEAD') | Select-Object -First 1)).Trim()
|
||||
$ownerHash = (Get-FileHash -LiteralPath (Join-Path $fixtureFull 'Owner.md') -Algorithm SHA1).Hash.ToLowerInvariant()
|
||||
|
||||
Set-Content -LiteralPath (Join-Path $fixtureFull 'packet.md') -Encoding utf8 -Value @"
|
||||
---
|
||||
packet_id: TEST-01
|
||||
candidate_identity: raw-sha1-manifest-recorded-below
|
||||
---
|
||||
|
||||
# Packet
|
||||
|
||||
``````text
|
||||
$ownerHash Owner.md
|
||||
``````
|
||||
"@
|
||||
Set-Content -LiteralPath (Join-Path $fixtureFull 'pass.md') -Encoding utf8 -Value @"
|
||||
---
|
||||
pass_id: TEST-01
|
||||
intake_base_commit: $baseCommit
|
||||
---
|
||||
|
||||
# Pass
|
||||
|
||||
## Phase-boundary intake
|
||||
|
||||
| Proposal or handoff note | Disposition | Reason or destination |
|
||||
| --- | --- | --- |
|
||||
"@
|
||||
|
||||
$workingNote = 'Kalsa/Spoilers/Reference/Working Handoff.md'
|
||||
Set-Content -LiteralPath (Join-Path $fixtureFull $workingNote) -Encoding utf8 -Value "---`nstatus: adopted-candidate`n---`n`n# Working handoff`n"
|
||||
Assert-CheckerFails -Boundary 'review' -Message 'Intake checker failed to reject an untracked handoff outside the packet'
|
||||
Invoke-FixtureGit -Arguments @('add', '--', $workingNote) | Out-Null
|
||||
Assert-CheckerFails -Boundary 'review' -Message 'Intake checker failed to reject a staged handoff outside the packet'
|
||||
Invoke-FixtureGit -Arguments @('reset', 'HEAD', '--', $workingNote) | Out-Null
|
||||
|
||||
Add-Content -LiteralPath (Join-Path $fixtureFull 'pass.md') -Encoding utf8 -Value "| ``$workingNote`` | defer | Route to TEST-02 before integration. |"
|
||||
& (Join-Path $PSScriptRoot 'check-phase-boundary-intake.ps1') `
|
||||
-Boundary review `
|
||||
-PacketPath 'packet.md' `
|
||||
-PassPath 'pass.md' `
|
||||
-RepositoryRoot $fixtureFull | Out-Null
|
||||
|
||||
$committedNote = 'Kalsa/Spoilers/Reference/Committed Proposal.md'
|
||||
Set-Content -LiteralPath (Join-Path $fixtureFull $committedNote) -Encoding utf8 -Value "---`nstatus: proposal`n---`n`n# Committed proposal`n"
|
||||
Invoke-FixtureGit -Arguments @('add', '--', $committedNote) | Out-Null
|
||||
Invoke-FixtureGit -Arguments @('-c', 'user.name=Kalsa Tests', '-c', 'user.email=kalsa-tests@example.invalid', 'commit', '-m', 'Add proposal during pass') | Out-Null
|
||||
Assert-CheckerFails -Boundary 'closure' -Message 'Intake checker failed to reject a committed proposal outside the packet'
|
||||
|
||||
Add-Content -LiteralPath (Join-Path $fixtureFull 'pass.md') -Encoding utf8 -Value "| ``$committedNote`` | reject | Superseded by the named owner record. |"
|
||||
& (Join-Path $PSScriptRoot 'check-phase-boundary-intake.ps1') `
|
||||
-Boundary closure `
|
||||
-PacketPath 'packet.md' `
|
||||
-PassPath 'pass.md' `
|
||||
-RepositoryRoot $fixtureFull | Out-Null
|
||||
|
||||
$includedNote = 'Kalsa/Spoilers/Reference/Included Handoff.md'
|
||||
Set-Content -LiteralPath (Join-Path $fixtureFull $includedNote) -Encoding utf8 -Value "---`ntype: handoff`n---`n`n# Included handoff`n"
|
||||
$includedHash = (Get-FileHash -LiteralPath (Join-Path $fixtureFull $includedNote) -Algorithm SHA1).Hash.ToLowerInvariant()
|
||||
Add-Content -LiteralPath (Join-Path $fixtureFull 'packet.md') -Encoding utf8 -Value "$includedHash $includedNote"
|
||||
& (Join-Path $PSScriptRoot 'check-phase-boundary-intake.ps1') `
|
||||
-Boundary review `
|
||||
-PacketPath 'packet.md' `
|
||||
-PassPath 'pass.md' `
|
||||
-RepositoryRoot $fixtureFull | Out-Null
|
||||
|
||||
Add-Content -LiteralPath (Join-Path $fixtureFull $includedNote) -Encoding utf8 -Value "Changed after freeze."
|
||||
Assert-CheckerFails -Boundary 'closure' -Message 'Intake checker failed to reject a packeted handoff changed after freeze'
|
||||
|
||||
Write-Output 'Phase-boundary intake tests passed for committed, staged/working, deferred, rejected, packeted, and post-freeze-changed notes.'
|
||||
}
|
||||
finally {
|
||||
$resolvedFixture = [System.IO.Path]::GetFullPath($fixtureFull)
|
||||
if ($resolvedFixture.StartsWith($tempBase + [System.IO.Path]::DirectorySeparatorChar, [System.StringComparison]::OrdinalIgnoreCase) -and
|
||||
([System.IO.Path]::GetFileName($resolvedFixture) -like 'kalsa-phase-intake-*') -and
|
||||
(Test-Path -LiteralPath $resolvedFixture)) {
|
||||
Remove-Item -LiteralPath $resolvedFixture -Recurse -Force
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue