AITriad.psm1
|
# Copyright (c) 2026 Jeffrey Snover. All rights reserved. # Licensed under the MIT License. See LICENSE file in the project root. #Requires -Version 7.0 Set-StrictMode -Version Latest # ───────────────────────────────────────────────────────────────────────────── # Module root paths # Supports both dev layout (scripts/AITriad/) and PSGallery install (flat module dir) # ───────────────────────────────────────────────────────────────────────────── $script:ModuleRoot = $PSScriptRoot # Detect if we're in a dev repo (scripts/AITriad/) or a PSGallery install $_resolvedParent = Resolve-Path (Join-Path (Join-Path $PSScriptRoot '..') '..') -ErrorAction SilentlyContinue if ($_resolvedParent) { $_candidateRepoRoot = $_resolvedParent.Path } else { $_candidateRepoRoot = $null } if ($_candidateRepoRoot -and (Test-Path (Join-Path $_candidateRepoRoot '.aitriad.json'))) { $script:RepoRoot = $_candidateRepoRoot $script:IsDevInstall = $true } elseif ($_candidateRepoRoot -and (Test-Path (Join-Path $_candidateRepoRoot 'CLAUDE.md'))) { $script:RepoRoot = $_candidateRepoRoot $script:IsDevInstall = $true } else { # PSGallery or standalone install — module root IS the root $script:RepoRoot = $PSScriptRoot $script:IsDevInstall = $false } # ───────────────────────────────────────────────────────────────────────────── # ClaimsByPov — per-POV claim counts for AITSource objects # ───────────────────────────────────────────────────────────────────────────── class ClaimsByPov { [int]$Accelerationist [int]$Safetyist [int]$Skeptic [int]$Situations } # ───────────────────────────────────────────────────────────────────────────── # AITModelInfo — model and extraction parameters used to generate a summary # ───────────────────────────────────────────────────────────────────────────── class AITModelInfo { [string] $Model [double] $Temperature [int] $MaxTokens [string] $ExtractionMode # fire | single_shot | auto_fire [string] $TaxonomyFilter # rag | full | rag_per_chunk [int] $TaxonomyNodes [double] $FireConfidenceThreshold [bool] $Chunked [int] $ChunkCount [PSObject]$FireStats # api_calls, iterations, claims_total, etc. } # ───────────────────────────────────────────────────────────────────────────── # AITSource — typed representation of a source document + summary statistics # ───────────────────────────────────────────────────────────────────────────── class AITSource { [string] $Id [string] $Title [string] $Url [string[]] $Authors [string] $DatePublished [string] $DateIngested [string] $ImportTime [string] $SourceTime [string] $SourceType [string[]] $PovTags [string[]] $TopicTags [string[]] $RolodexAuthorIds [string] $ArchiveStatus [string] $SummaryVersion [string] $SummaryStatus [string] $SummaryUpdated [string] $OneLiner [string] $MDPath [string] $Directory # Provenance (populated from metadata.json provenance fields) [object] $Provenance [string] $ProvenanceStatus [string] $ResolvedUrl # Summary statistics (populated when summary exists) [int] $TotalClaims [ClaimsByPov] $ClaimsByPov [int] $TotalFacts [int] $UnmappedConcepts [AITModelInfo] $ModelInfo } Update-TypeData -TypeName AITSource -MemberType AliasProperty -MemberName DocId -Value Id -Force # ───────────────────────────────────────────────────────────────────────────── # AITDebate — typed representation of a debate session # ───────────────────────────────────────────────────────────────────────────── class AITDebate { [string] $Id [string] $Title [string] $Topic [DateTime] $CreatedAt [DateTime] $UpdatedAt [string] $Phase [string] $Audience [string] $Protocol [string] $SourceType [string] $SourceRef [string[]] $Debaters [double] $Temperature [string] $Model [string] $Origin [bool] $AdaptiveStaging [string] $Pacing [int] $TranscriptCount [int] $Rounds [int] $Statements [int] $Interventions [bool] $HasSynthesis [bool] $HasDiagnostics [bool] $HasHarvest [string] $FilePath } Update-TypeData -TypeName AITDebate -MemberType AliasProperty -MemberName DebateId -Value Id -Force # ───────────────────────────────────────────────────────────────────────────── # TaxonomyNode class — must live in .psm1 for PowerShell type resolution # ───────────────────────────────────────────────────────────────────────────── class TaxonomyNode { [string]$POV [string]$Id [string]$Label [string]$Description [string]$Category [string]$ParentId [string]$ParentRelationship [string]$ParentRationale [string[]]$Children [string[]]$CrossCuttingRefs [string[]]$SituationRefs # t/1588 — structural signals mirrored from lib/debate/severeTestScheduler.ts's # computeNodeImportance() so PS + TS derive `degree` and `usage` from the # same source. ConflictIds may be absent on nodes with no conflict links; # DoctrinallyAnchored defaults to $false; DebateRefs is the count-source # for the `usage` importance term. [string[]]$ConflictIds [bool]$DoctrinallyAnchored [string[]]$DebateRefs [PSObject]$Interpretations [string[]]$LinkedNodes [double]$Score [PSObject]$GraphAttributes [PSObject[]]$LabelHistory [PSObject[]]$DescriptionHistory [PSObject[]]$ChangeHistory [string]$PlainDescription [string]$PlainDescriptionVersion } # ───────────────────────────────────────────────────────────────────────────── # AITClaim — typed representation of an extracted claim (factual or key point) # ───────────────────────────────────────────────────────────────────────────── class AITClaim { [string] $DocId [string] $Type # FactualClaim | KeyPoint [string] $Text [string] $Label # claim_label (FactualClaim only) [string] $POV # accelerationist/safetyist/skeptic (KeyPoint only) [string] $Category # BDI category (KeyPoint only) [string] $Stance # aligned/neutral/opposed (KeyPoint only) [string] $DocPosition # supports/contradicts/discusses (FactualClaim only) [string] $TemporalScope # historical/predictive/timeless (FactualClaim only) [string] $TemporalBound # date bound (FactualClaim only) [double] $Confidence # extraction_confidence [double] $FireConfidence # fire_confidence (FactualClaim only) [string[]] $LinkedNodes # taxonomy node IDs [string] $Specificity # evidence_criteria.specificity (FactualClaim only) [bool] $HasWarrant # evidence_criteria.has_warrant (FactualClaim only) [string] $EvidenceLevel # evidence_criteria.category_criteria.evidence_level (FactualClaim only) [string] $Verbatim # verbatim quote (KeyPoint only) } # ───────────────────────────────────────────────────────────────────────────── # HealthCheck — individual check result from Test-TaxEditorHealth # ───────────────────────────────────────────────────────────────────────────── class HealthCheck { [string] $Endpoint [string] $Purpose [int] $Status [bool] $Healthy [int] $Ms [string] $Detail } # ───────────────────────────────────────────────────────────────────────────── # TaxEditorHealthResult — overall result from Test-TaxEditorHealth # ───────────────────────────────────────────────────────────────────────────── class TaxEditorHealthResult { [string] $BaseUrl [bool] $Healthy [HealthCheck[]] $Checks [int] $AverageMs [int] $FreeTierKeyPoolSize [string] $Timestamp } # ───────────────────────────────────────────────────────────────────────────── # AcaRevision — typed result from Get-TaxEditorRevision # ───────────────────────────────────────────────────────────────────────────── class AcaRevision { [string] $Name [bool] $Active [int] $TrafficWeight [string] $RunningState [string] $ImageTag [string] $CreatedAt } # ───────────────────────────────────────────────────────────────────────────── # GhcrImage — typed result from Get-TaxEditorImage # ───────────────────────────────────────────────────────────────────────────── class GhcrImage { [string[]] $Tags [string] $Digest [string] $CreatedAt [bool] $IsKnownGood } # ───────────────────────────────────────────────────────────────────────────── # DataCommit — typed result from Get-TaxEditorDataCommit # ───────────────────────────────────────────────────────────────────────────── class DataCommit { [string] $Sha [string] $ShortSha [string] $Message [string] $Author [string] $Date } # ───────────────────────────────────────────────────────────────────────────── # BlobInfo — typed result from Get-TaxEditorBlob # ───────────────────────────────────────────────────────────────────────────── class BlobInfo { [string] $Name [string] $Container [long] $Size [string] $LastModified [bool] $Deleted [string] $DeletedAt } # ───────────────────────────────────────────────────────────────────────────── # EndpointTestResult — typed result from Test-TaxEditorEndpoints # ───────────────────────────────────────────────────────────────────────────── class EndpointTestResult { [string] $Endpoint [string] $Category [string] $Description [int] $Status [bool] $Pass [int] $Ms [object] $NodeCount [string] $Error } class AnonymousFlowStepResult { [int] $Step [string] $Method [string] $Endpoint [string] $Description [string] $BugTags [bool] $Pass [int] $StatusCode [int] $Ms [string] $Error } # ───────────────────────────────────────────────────────────────────────────── # StaleImageCleanupResult — typed result from Remove-StaleContainerImages (t/1492) # ───────────────────────────────────────────────────────────────────────────── class StaleImageCleanupResult { [string] $Package [string] $Owner [int] $TotalUntagged [int] $KeptCount [int] $DeletedCount [long[]] $DeletedIds [string[]] $Failures [string] $CutoffUtc } # ───────────────────────────────────────────────────────────────────────────── # TaxonomySnapshotResult — typed result from Get-TaxonomySnapshot (t/1493) # ───────────────────────────────────────────────────────────────────────────── class TaxonomySnapshotResult { [string] $OutputPath [string] $Repo [string] $Branch [string] $Commit [string] $Generated [object[]] $Files [bool] $Valid [string[]] $MissingRequired [string] $SnapshotMetaPath } # ───────────────────────────────────────────────────────────────────────────── # ContainerAppRevisionInfo — typed result from Get-ContainerAppRevision (t/1498) # ───────────────────────────────────────────────────────────────────────────── class ContainerAppRevisionInfo { [string] $Name [int] $TrafficWeight [bool] $Active [string] $Fqdn [string] $CreatedTime } # ───────────────────────────────────────────────────────────────────────────── # GitHubWorkflowJobInfo / GitHubWorkflowRunInfo — typed results # from Get-GitHubWorkflowRun (t/1499) # ───────────────────────────────────────────────────────────────────────────── class GitHubWorkflowJobInfo { [string] $Name [string] $Status [string] $Conclusion } class GitHubWorkflowRunInfo { [long] $RunId [string] $Status [string] $Conclusion [string] $HeadSha [string] $Url [GitHubWorkflowJobInfo[]] $Jobs } class FreeTierStatus { [string] $Tier [int] $DailyTokenBudget [int] $TokensUsedToday [int] $TokensRemainingToday [double] $BudgetUtilizationPct [int] $RPMLimit [string[]] $AllowedRoutes [object] $MilestoneWarnings [string] $LastResetTime [string] $BaseUrl } class EdgeTypeResolution { [string] $Action # accept | reclassify | drop [string] $Type # canonical type when accept/reclassify; empty when drop [string] $Reason # human-readable explanation for reclassify/drop } class ServiceWorkerHealthCheck { [string] $Name [bool] $Pass [string] $Detail } class ServiceWorkerHealth { [string] $BaseUrl [bool] $FetchedOk [int] $StatusCode [int] $Bytes [string] $Hash [string] $SkipWaitingMode # auto | message | none [bool] $ClientsClaim [string[]] $Denylist [string[]] $MissingDenylist [string] $NavigateFallback [int] $PrecacheCount [object[]] $PrecacheManifest [ServiceWorkerHealthCheck[]] $Checks [bool] $OverallPass } class PersonaEndpointTestResult { [string] $Persona [string] $Method [string] $Endpoint [string] $Category [bool] $ExpectedAccess # true = expected 2xx, false = expected 401/403 [bool] $ActualAccess # true = got 2xx, false = got 401/403 (or 200-but-shell) [bool] $Pass # ExpectedAccess == ActualAccess after shell reclassification (t/1355) [int] $StatusCode [string] $ContentType # t/1355 — used to distinguish real JSON response from SPA fall-through [string] $BodyKind # t/1355 — 'json' | 'html' | 'empty' | 'unparsed' [int] $Ms [string] $Note # 'skipped: no PersonaSecret'; '200-but-SPA-shell' etc. [string] $Error } # t/1224 — Organization data model. Mirrors the HLD at t/1217#1 plus the # policy_engagement field added per TL guidance. class OrganizationPovAlignment { [double] $Score # -1.0 .. 1.0 [string] $Rationale } class OrganizationTopicEngagement { [string] $TopicRef # sit-NNN [string] $Stance # advocate | opponent | researcher | neutral [string] $Description } class OrganizationPolicyEngagement { [string] $PolicyRef # pol-NNN [string] $Stance # supports | opposes } class OrganizationKeyFigure { [string] $Name [string] $Role [string] $Relevance } class OrganizationExternalLink { [string] $Type # website | position_paper | report | blog | social | wikipedia | legislation [string] $Url [string] $Title } # t/1560 — derived per-camp alignment (mirrors PovAlignmentDerivedPerCamp # in lib/organizations/types.ts). Three-state: PovAlignmentDerived null on # the Organization = never computed; NetRatio null with N=0 = computed, # no data; NetRatio non-null = computed with data. Do NOT collapse # NetRatio to 0.0 default — erases the "no data" signal (TL t/1560#4). class OrganizationPovAlignmentDerivedPerCamp { [int] $Advocates [int] $Opposes [int] $N [System.Nullable[double]] $NetRatio } class OrganizationPovAlignmentDerivedProvenance { [string] $ComputedAt [string] $CmdletVersion [string] $InputEdgesSha [string[]] $IncludedStatusFilter [int] $EdgeCount } class OrganizationPovAlignmentDerived { [OrganizationPovAlignmentDerivedPerCamp] $Acc [OrganizationPovAlignmentDerivedPerCamp] $Saf [OrganizationPovAlignmentDerivedPerCamp] $Skp [OrganizationPovAlignmentDerivedProvenance] $Provenance } # ───────────────────────────────────────────────────────────────────────────── # NodeTestingRecord — typed emit from Get-NodeTestingRecord (t/1579 Phase 2). # Read-only projection of graph_attributes.debate_tested onto a # pipeline-composable shape for research users. # ───────────────────────────────────────────────────────────────────────────── class NodeTestingRecord { [string] $NodeId [string] $Pov # accelerationist | safetyist | skeptic [string] $Category # Beliefs | Desires | Intentions [string] $Label [string] $Tier # untested | cited | contested | well_tested [double] $SortKey [int] $Engagements [int] $Challenges [int] $Held [int] $Weakened [string] $LastTested [bool] $Refined # true if any revision has held_since [bool] $Stale # description_hash mismatch (see help for exemption) [string[]] $ChallengerCamps # distinct camps in record[] [double] $Importance # populated only when -SortBy Deficit [double] $Deficit # populated only when -SortBy Deficit [double] $TestingPriority # importance * deficit, only when -SortBy Deficit } class Organization { [string] $Id # org-NNN [string] $Name [string] $ShortName [string] $Type # think_tank | advocacy | regulatory | academic | corporate | intergovernmental | civil_society | standards_body | research_lab [string] $Description [string] $Url [string] $Headquarters [int] $Founded [string] $Status # active | dissolved | merged [hashtable] $PovAlignment # 'accelerationist'|'safetyist'|'skeptic' → OrganizationPovAlignment [OrganizationPovAlignmentDerived] $PovAlignmentDerived # t/1560; $null when never computed [OrganizationTopicEngagement[]] $TopicEngagement [OrganizationPolicyEngagement[]] $PolicyEngagement [OrganizationKeyFigure[]] $KeyFigures [OrganizationExternalLink[]] $ExternalLinks [string[]] $SourceRefs [string[]] $Tags [string] $CreatedAt [string] $LastModified } class OrganizationStakeholders { [string] $PolicyId [Organization[]] $Supporters [Organization[]] $Opposers } class OrganizationIntegrityIssue { [string] $OrgId [string] $Severity # error | warning [string] $Field [string] $Message } class OrganizationIntegrityReport { [int] $Total [int] $Errors [int] $Warnings [bool] $Pass [OrganizationIntegrityIssue[]] $Issues } # t/1526 — Organization actor-relationship edges (parallel to argumentation edges.json) class OrganizationEdge { [string] $Source # org-* [string] $Target # org-* | sit-* | pol-* | src-* | BDI node id, per type family [string] $Type # one of Resolve-OrganizationEdgeType 9-value registry [string] $Rationale [string[]] $SourceRefs [string] $Status # approved | proposed | disputed | rejected (default: approved) [string] $DiscoveredAt # YYYY-MM-DD } class OrganizationEdgeIntegrityIssue { [int] $EdgeIndex [string] $Source [string] $Target [string] $Type [string] $Severity # error | warning [string] $Field [string] $Message } class OrganizationEdgeIntegrityReport { [int] $Total [int] $Errors [int] $Warnings [bool] $Pass [OrganizationEdgeIntegrityIssue[]] $Issues } # ───────────────────────────────────────────────────────────────────────────── # Module-scoped taxonomy store # ───────────────────────────────────────────────────────────────────────────── $script:TaxonomyData = @{} $script:TaxonomyFileTimestamps = @{} # file path → LastWriteTime for staleness detection $script:CachedEmbeddings = $null # Lazy-loaded by Get-RelevantTaxonomyNodes $script:EmbeddingsTimestamp = $null # LastWriteTime of embeddings.json $script:CachedSyntheticVectors = $null # Lazy-loaded (multi-vector synthetic embeddings) $script:SyntheticTimestamp = $null # LastWriteTime of synthetic_embeddings.json $script:TaxonomyCacheLastCheck = $null # UTC time of last staleness check (cooldown) # ───────────────────────────────────────────────────────────────────────────── # Load ai-models.json — single source of truth for backend/model lists # ───────────────────────────────────────────────────────────────────────────── $script:AIModelConfig = $null $script:ValidModelIds = @() # Try repo root first (dev), then module root (PSGallery install) $AIModelsPath = Join-Path $script:RepoRoot 'ai-models.json' if (-not (Test-Path $AIModelsPath)) { $AIModelsPath = Join-Path $script:ModuleRoot 'ai-models.json' } if (Test-Path $AIModelsPath) { try { $script:AIModelConfig = Get-Content -Raw -Path $AIModelsPath | ConvertFrom-Json $script:ValidModelIds = @($script:AIModelConfig.models | ForEach-Object { $_.id }) Write-Verbose "AI Models: loaded $($script:ValidModelIds.Count) models from ai-models.json" } catch { Write-Warning "AI Models: failed to load ai-models.json — $($_.Exception.Message)" } } # ───────────────────────────────────────────────────────────────────────────── # Dot-source Private/ then Public/ functions # ───────────────────────────────────────────────────────────────────────────── foreach ($Scope in @('Private', 'Public')) { $Dir = Join-Path $PSScriptRoot $Scope if (Test-Path $Dir) { foreach ($File in Get-ChildItem -Path $Dir -Filter '*.ps1' -File -Recurse) { . $File.FullName } } } # ───────────────────────────────────────────────────────────────────────────── # Import companion modules # Dev: scripts/ dir (parent of AITriad/) # PSGallery: bundled in module root alongside AITriad.psm1 # ───────────────────────────────────────────────────────────────────────────── $_companionDirs = @( (Join-Path $script:ModuleRoot '..') # Dev layout: scripts/ $script:ModuleRoot # PSGallery: bundled in module root ) foreach ($_name in @('DocConverters', 'AIEnrich')) { $_loaded = $false foreach ($_dir in $_companionDirs) { $_path = Join-Path $_dir "$_name.psm1" if (Test-Path $_path) { try { Import-Module $_path -Force $_loaded = $true break } catch { Write-Warning "Failed to import ${_name}.psm1: $_ — related features will be unavailable." } } } if (-not $_loaded) { Write-Verbose "${_name}.psm1 not found — related features will be unavailable." } } # ───────────────────────────────────────────────────────────────────────────── # Load taxonomy data at import time (same logic as standalone Taxonomy.psm1) # ───────────────────────────────────────────────────────────────────────────── $TaxonomyDir = Get-TaxonomyDir if (Test-Path $TaxonomyDir) { foreach ($File in Get-ChildItem -Path $TaxonomyDir -Filter '*.json' -File) { if ($File.Name -in 'embeddings.json', 'edges.json', 'policy_actions.json', '_archived_edges.json', 'lineage_categories.json', 'interpretation_embeddings.json', 'source_evidence_index.json', 'similarity-cache.json') { continue } # Embedding-variant files (e.g. embeddings-orgstance-6733.json, t/524) are legitimately # large (50MB+, ~9,500 orgs x 1,536-dim vectors) and carry no .nodes array — they are # loaded on demand by org-stance cmdlets, never by this POV loop. Skip them BEFORE the # corruption guard so they neither trip the 10MB POV-corruption warning (t/1645) nor get # parsed-then-discarded 13x per batch run. The 10MB guard below still protects POV files. if ($File.Name -like 'embeddings-*.json' -or $File.Name -like '*-embeddings.json') { continue } if ($File.Length -gt 10MB) { Write-Warning "Taxonomy: skipping $($File.Name) — file is $([math]::Round($File.Length / 1MB, 1)) MB (likely corrupted, max 10 MB)." continue } try { $Json = Get-Content -Raw -Path $File.FullName | ConvertFrom-Json # Only register POV files that follow the taxonomy-node shape (a .nodes # array whose entries carry an 'id'). Auxiliary files (lineage_categories.json) # and sidecar logs (entity_extraction_log.json, whose nodes are keyed by # 'node_id' — t/1834) live alongside POV files but must NOT be treated as POVs. if (-not (Test-IsPovTaxonomyData $Json)) { Write-Verbose "Taxonomy: skipping $($File.Name) (not a POV node file — no id-shaped nodes[])" continue } $PovName = $File.BaseName.ToLower() $script:TaxonomyData[$PovName] = $Json $script:TaxonomyFileTimestamps[$File.FullName] = $File.LastWriteTime Write-Verbose "Taxonomy: loaded '$PovName' ($($Json.nodes.Count) nodes) from $($File.Name)" } catch { Write-Warning "Taxonomy: failed to load $($File.Name): $_ — this POV will be unavailable until the file is fixed." } } } if ($script:TaxonomyData.Count -eq 0) { Write-Warning "Taxonomy: no valid JSON files loaded from $TaxonomyDir — most commands will not work." } # Load policy registry $script:PolicyRegistry = $null $RegistryFile = Join-Path $TaxonomyDir 'policy_actions.json' if (Test-Path $RegistryFile) { try { $script:PolicyRegistry = Get-Content -Raw -Path $RegistryFile | ConvertFrom-Json Write-Verbose "Policy registry: loaded $($script:PolicyRegistry.policy_count) policies" } catch { Write-Warning "Policy registry: failed to load — $($_.Exception.Message)" } } # ───────────────────────────────────────────────────────────────────────────── # Backward-compatibility & convenience aliases # ───────────────────────────────────────────────────────────────────────────── Set-Alias -Name 'Import-Document' -Value 'Import-AITriadDocument' -Scope Global Set-Alias -Name 'TaxonomyEditor' -Value 'Show-TaxonomyEditor' -Scope Global Set-Alias -Name 'POViewer' -Value 'Show-POViewer' -Scope Global Set-Alias -Name 'SummaryViewer' -Value 'Show-SummaryViewer' -Scope Global Set-Alias -Name 'Redo-Snapshots' -Value 'Update-Snapshot' -Scope Global Set-Alias -Name 'Install-AITdependencies' -Value 'Install-AIDependencies' -Scope Global Set-Alias -Name 'Workflow' -Value 'Show-WorkflowRunner' -Scope Global # ───────────────────────────────────────────────────────────────────────────── # Deprecation wrappers — old cmdlet names delegate to new names # ───────────────────────────────────────────────────────────────────────────── function Find-CrossCuttingCandidates { <# .SYNOPSIS DEPRECATED: Use Find-SituationCandidates instead. #> [CmdletBinding()] param() Write-Warning (New-ActionableError -Goal 'run Find-CrossCuttingCandidates' ` -Problem 'Find-CrossCuttingCandidates was renamed in the Situations migration' ` -Location 'AITriad module' ` -NextSteps 'Use Find-SituationCandidates instead' ` -PassThru) Find-SituationCandidates @PSBoundParameters } # ───────────────────────────────────────────────────────────────────────────── # Export public surface # ───────────────────────────────────────────────────────────────────────────── Export-ModuleMember -Function @( 'Get-Tax' 'Update-TaxEmbeddings' 'Import-AITriadDocument' 'Invoke-POVSummary' 'Invoke-BatchSummary' 'Find-Conflict' 'Find-AITSource' 'Save-AITSource' 'Save-WaybackUrl' 'Invoke-PIIAudit' 'Update-Snapshot' 'Show-TaxonomyEditor' 'Show-POViewer' 'Show-SummaryViewer' 'Show-AITriadHelp' 'Get-TaxonomyHealth' 'Measure-TaxonomyBaseline' 'Invoke-TaxonomyProposal' 'Compare-Taxonomy' 'Get-AITSource' 'Get-AITDebate' 'Repair-PovDescriptions' 'Repair-PovLineage' 'Repair-PovAttributes' 'Export-AggregatedCruxes' 'Get-Summary' 'Invoke-AttributeExtraction' 'Invoke-EdgeDiscovery' 'Get-GraphNode' 'Find-GraphPath' 'Approve-Edge' 'Approve-TaxonomyProposal' 'Get-Edge' 'Set-Edge' 'Invoke-GraphQuery' 'Get-ConflictEvolution' 'Export-TaxonomyToGraph' 'Install-GraphDatabase' 'Invoke-CypherQuery' 'Show-GraphOverview' 'Get-TopicFrequency' 'Get-IngestionPriority' 'Find-SituationCandidates' 'Find-CrossCuttingCandidates' 'Show-TriadDialogue' 'Register-AIBackend' 'Install-AITriadData' 'Install-AIDependencies' 'Test-Dependencies' 'Find-PossibleFallacy' 'Find-PolicyAction' 'Get-Policy' 'Update-PolicyRegistry' 'Show-FallacyInfo' 'Test-TaxonomyIntegrity' 'Invoke-HierarchyProposal' 'Set-TaxonomyHierarchy' 'Invoke-SchemaMigration' 'Invoke-PolicyRefinement' 'Repair-UnmappedConcepts' 'Invoke-AITDebate' 'Resume-AITDebate' 'Convert-MD2PDF' 'Show-Markdown' 'Show-DebateDiagnostics' 'Show-DebateHarvest' 'Repair-DebateOutput' 'Get-AITSBOM' 'Test-OntologyCompliance' 'Get-RelevantTaxonomyNodes' 'Invoke-QbafConflictAnalysis' 'Test-ExtractionQuality' 'Show-WorkflowRunner' 'Test-EdgeDirection' 'Test-AITJudgeModel' 'Repair-AITSummaryMappings' 'Repair-ResolvedBackfill' 'Invoke-EdgeWeightEvaluation' 'Repair-Markdown' 'Compare-DebateRuns' 'Compare-DebateQuality' 'Measure-DebateQuality' 'Invoke-DebateAB' 'Get-AICostReport' 'Show-OSSLicenses' 'Get-FlightRecorderDump' 'Get-LatestFlightRecorderDump' 'Get-AzureFlightRecorder' 'Show-FlightRecorder' 'Update-AITSourceIndex' 'Get-PovLineage' 'Get-IntellectualLineage' 'Invoke-BDIWeightAssignment' 'Register-AITriadDrive' 'Get-TaxonomyProcess' 'Request-FlightRecorderDump' 'Get-FlightRecorderReport' 'Get-AITClaim' 'Compare-EmbeddingModel' 'Test-RerankerBaseline' 'New-SyntheticCorpus' 'Update-SyntheticCorpus' 'Sync-SyntheticCorpus' 'Export-SyntheticEmbeddings' 'Test-SynthesisCompleteness' 'Get-ImportReport' 'Get-CalibrationTrend' 'Test-TaxEditorHealth' 'Test-TaxEditorEndpoints' 'Test-AnonymousDebateFlow' 'Test-PersonaEndpoints' 'Test-ServiceWorkerHealth' 'Watch-DebateProgress' 'Invoke-DebateBatch' 'Get-FreeTierStatus' 'Invoke-TaxEditorSmokeTest' 'Test-AzureHealth' 'Test-GitHubHealth' 'Get-TaxEditorRevision' 'Switch-TaxEditorRevision' 'Get-TaxEditorDataCommit' 'Undo-TaxEditorDataCommit' 'Sync-TaxEditorData' 'Reset-TaxEditorSession' 'Get-TaxEditorImage' 'Deploy-TaxEditorImage' 'Set-TaxEditorKnownGood' 'Restore-TaxEditorKnownGood' 'Test-TaxEditorInfra' 'Deploy-TaxEditorInfra' 'Get-TaxEditorBlob' 'Restore-TaxEditorBlob' 'Get-CriticalInteraction' 'Test-CriticalInteractions' 'Merge-FlightRecorderDumps' 'Get-TriadConfig' 'Set-TriadConfig' 'Invoke-TriadConfigReload' 'Invoke-VernacularBatch' # t/1224 — Organization data model 'Get-Organization' 'Find-OrganizationByPOV' 'Find-OrganizationByTopic' 'Get-OrganizationStakeholders' 'Import-Organization' 'Compare-OrganizationPositions' # t/1526 — Organization actor-relationship edges 'Get-OrganizationEdge' 'Import-OrganizationEdge' # t/1804 — Entity ontology (Phase 1): store + curation cmdlets 'Get-Entity' 'Import-Entity' # t/1261 — UsageID registry 'Invoke-AIByUsage' # t/1308 — cc→sit migration 'Invoke-CcToSitMigration' 'Test-AIApiKey' 'Test-AIModelsConfig' # t/1492 — GHCR cleanup 'Remove-StaleContainerImages' # t/1493 — Taxonomy snapshot fetch 'Get-TaxonomySnapshot' # t/1498 — ACA revision queries 'Get-ContainerAppRevision' # t/1499 — GH workflow run queries 'Get-GitHubWorkflowRun' # t/1550 — POV aphorism backfill 'Invoke-AphorismBatch' # t/1553 Stage 0 — org PUBLISHED edge seeding 'Invoke-OrgPublishedSeeding' # t/1553 Stage 1 — org stance claim extraction 'Invoke-OrgStanceExtraction' # t/1553 Stages 2+3 — claim→node matching + edge proposal aggregation 'Invoke-OrgClaimMatching' # t/1560 Stage 5 — R2 rollup, per-camp derived alignment from approved edges 'Invoke-OrgDerivedCampScores' # t/1500 Phase 3 — blue-green deploy orchestration (e/41) 'Disable-ContainerAppRevision' 'New-ContainerAppRevision' 'Set-ContainerAppTraffic' 'Get-ContainerAppDiagnostics' # t/1579 — Debate-Tested Phase 2 research surface 'Get-NodeTestingRecord' 'Update-NodeTestingRecord' # t/1654 — pre-embedding TAXONOMY_DIR validation 'Test-TaxonomyDirContents' # t/1806 — Entity ontology Phase 1: extraction + maintenance reports 'Invoke-EntityExtraction' 'Get-EntityReport' # t/1894 — Entity ontology Phase 2-B: batch mention indexer (entity_mentions.json) 'Update-EntityMentionIndex' ) -Alias @( 'Import-Document' 'TaxonomyEditor' 'POViewer' 'SummaryViewer' 'Redo-Snapshots' 'Show-MD' 'Workflow' ) # ───────────────────────────────────────────────────────────────────────────── # Register -Model argument completers (module-scoped, captures $script:ValidModelIds) # ───────────────────────────────────────────────────────────────────────────── $_modelCompleter = { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $script:ValidModelIds | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object { [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_) } } foreach ($_cmd in @( 'Invoke-POVSummary', 'Invoke-BatchSummary', 'Invoke-AttributeExtraction', 'Invoke-EdgeDiscovery', 'Invoke-GraphQuery', 'Invoke-TaxonomyProposal', 'Invoke-HierarchyProposal', 'Invoke-PolicyRefinement', 'Invoke-AITDebate', 'Import-AITriadDocument', 'Find-PolicyAction', 'Find-PossibleFallacy', 'Find-SituationCandidates', 'Get-ConflictEvolution', 'Get-Edge', 'Get-IngestionPriority', 'Get-RelevantTaxonomyNodes', 'Get-TopicFrequency', 'Show-TriadDialogue' )) { Register-ArgumentCompleter -CommandName $_cmd -ParameterName 'Model' -ScriptBlock $_modelCompleter } |