Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions skills/custom/d-ai/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ An explicit `@D-AI` command overrides the natural-language default. In particula
- `--task <task-id>` selects a durable task in a fresh Codex process.
- `--workspace <path>` selects the target workspace; otherwise use the current workspace.
3. Run this Skill's `scripts/invoke.ps1` with `-CommandText`, `-WorkspacePath`, and optional `-TaskId`; natural-language text is passed unchanged when it is the default entry.
The installed Skill root must contain a machine-local `.runtime-root` file pointing to a validated D-AI-Hub runtime checkout. Establish or switch that binding with `scripts/set-runtime-binding.ps1 -SkillRoot <installed-skill-root> -RuntimeRoot <d-ai-hub-checkout>`; a missing or invalid binding fails closed.
4. Report the returned status, message, and evidence without converting `BLOCKED` or `NO` into completion.

For `@D-AI status` and `@D-AI close`, omit `--task` on the normal path. The runtime discovers the unique active durable task for the current workspace. If there are zero matches, multiple matches, or an ownership/workspace conflict, keep the result `BLOCKED` and follow the returned retry guidance.
Expand Down
92 changes: 85 additions & 7 deletions skills/custom/d-ai/scripts/invoke.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,93 @@ param(
)

$ErrorActionPreference = 'Stop'

function Write-Blocked([string]$Message) {
[Console]::Out.WriteLine((([ordered]@{
status = 'blocked'
taskId = 'unassigned'
environment = 'codex'
stage = 'bootstrap'
message = $Message
} | ConvertTo-Json -Compress)))
}

function Assert-FullyQualifiedPath([string]$Path, [string]$Label) {
if ([string]::IsNullOrWhiteSpace($Path)) {
throw "$Label is empty"
}
if ($Path -notmatch '^(?:[A-Za-z]:[\\/]|\\\\)') {
throw "$Label must be a fully qualified absolute path"
}
}

function Resolve-Directory([string]$Path, [string]$Label) {
Assert-FullyQualifiedPath $Path $Label
$resolved = Resolve-Path -LiteralPath $Path -ErrorAction Stop
$item = Get-Item -LiteralPath $resolved.Path -Force
if (-not $item.PSIsContainer) {
throw "$Label is not a directory: $Path"
}
return $resolved.Path
}

function Assert-InstalledSkillRoot([string]$Candidate) {
Assert-FullyQualifiedPath $Candidate 'Installed D-AI Skill root'
$skillManifestPath = Join-Path $Candidate 'SKILL.md'
if (-not (Test-Path -LiteralPath $skillManifestPath -PathType Leaf)) {
throw 'Installed D-AI Skill root is invalid: SKILL.md is missing'
}
$skillManifest = Get-Content -LiteralPath $skillManifestPath -Raw
if ($skillManifest -notmatch '(?m)^name:\s*d-ai\s*$') {
throw 'Installed D-AI Skill root is invalid: SKILL.md is not the d-ai Skill'
}
foreach ($scriptName in @('invoke.ps1', 'set-runtime-binding.ps1')) {
if (-not (Test-Path -LiteralPath (Join-Path $Candidate "scripts\\$scriptName") -PathType Leaf)) {
throw "Installed D-AI Skill root is invalid: scripts/$scriptName is missing"
}
}
}

function Test-RuntimeRoot([string]$Candidate, [ref]$FailureReason) {
try {
$packagePath = Join-Path $Candidate 'package.json'
if (-not (Test-Path -LiteralPath $packagePath -PathType Leaf)) {
throw 'package.json is missing'
}
$package = Get-Content -LiteralPath $packagePath -Raw | ConvertFrom-Json
if ([string]::IsNullOrWhiteSpace([string]$package.scripts.'d-ai')) {
throw 'package.json does not define the d-ai npm script'
}
if (-not (Test-Path -LiteralPath (Join-Path $Candidate 'src\entry\codex-cli.ts') -PathType Leaf)) {
throw 'canonical D-AI Codex entry is missing'
Comment on lines +67 to +72

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Verify the bound repository identity before executing it

When .runtime-root points to an obsolete worktree or unrelated directory containing a package.json with any nonempty d-ai script plus src/entry/codex-cli.ts, this check accepts it and line 117 executes that package script. A binding can therefore silently route durable commands through the wrong implementation—or execute an arbitrary npm command—despite being presented as a validated canonical D-AI-Hub checkout; verify the Git repository/remote identity and intended canonical revision rather than only these filenames.

AGENTS.md reference: AGENTS.md:L15-L19

Useful? React with 👍 / 👎.

}
return $true
} catch {
$FailureReason.Value = $_.Exception.Message
return $false
}
}

$skillRoot = Split-Path -Parent $PSScriptRoot
$skillEntry = Get-Item -LiteralPath $skillRoot -Force
$canonicalSkillRoot = if ($null -ne $skillEntry.Target -and $skillEntry.Target.Count -gt 0) {
(Resolve-Path -LiteralPath @($skillEntry.Target)[0]).Path
} else {
(Resolve-Path -LiteralPath $skillRoot).Path
$repositoryRoot = $null
try {
Assert-InstalledSkillRoot $skillRoot
$bindingPath = Join-Path $skillRoot '.runtime-root'
if (-not (Test-Path -LiteralPath $bindingPath -PathType Leaf)) {
throw "Installed D-AI runtime binding is missing: $bindingPath"
}
$bindingValue = (Get-Content -LiteralPath $bindingPath -Raw).Trim()
$repositoryRoot = Resolve-Directory $bindingValue 'Installed D-AI runtime binding'
$failureReason = ''
if (-not (Test-RuntimeRoot $repositoryRoot ([ref]$failureReason))) {
throw "Installed D-AI runtime binding is invalid: $failureReason"
}
$npm = (Get-Command npm.cmd -ErrorAction Stop).Source
} catch {
Write-Blocked $_.Exception.Message
exit 2
}
$repositoryRoot = (Resolve-Path -LiteralPath (Join-Path $canonicalSkillRoot '..\..\..')).Path
$npm = (Get-Command npm.cmd -ErrorAction Stop).Source

$arguments = @(
'--silent',
'--prefix',
Expand Down
87 changes: 87 additions & 0 deletions skills/custom/d-ai/scripts/set-runtime-binding.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string]$SkillRoot,

[Parameter(Mandatory = $true)]
[string]$RuntimeRoot
)

$ErrorActionPreference = 'Stop'

function Assert-FullyQualifiedPath([string]$Path, [string]$Label) {
if ([string]::IsNullOrWhiteSpace($Path)) {
throw "$Label is empty"
}
if ($Path -notmatch '^(?:[A-Za-z]:[\\/]|\\\\)') {
throw "$Label must be a fully qualified absolute path"
}
}

function Resolve-Directory([string]$Path, [string]$Label) {
Assert-FullyQualifiedPath $Path $Label
$resolved = Resolve-Path -LiteralPath $Path -ErrorAction Stop
$item = Get-Item -LiteralPath $resolved.Path -Force
if (-not $item.PSIsContainer) {
throw "$Label is not a directory: $Path"
}
return $resolved.Path
}

function Assert-RuntimeRoot([string]$Candidate) {
$packagePath = Join-Path $Candidate 'package.json'
if (-not (Test-Path -LiteralPath $packagePath -PathType Leaf)) {
throw "Runtime root is invalid: package.json is missing"
}
$package = Get-Content -LiteralPath $packagePath -Raw | ConvertFrom-Json
if ([string]::IsNullOrWhiteSpace([string]$package.scripts.'d-ai')) {
throw "Runtime root is invalid: package.json does not define the d-ai npm script"
}
if (-not (Test-Path -LiteralPath (Join-Path $Candidate 'src\entry\codex-cli.ts') -PathType Leaf)) {
throw 'Runtime root is invalid: canonical D-AI Codex entry is missing'
}
}

function Assert-InstalledSkillRoot([string]$Candidate) {
Assert-FullyQualifiedPath $Candidate 'Installed D-AI Skill root'
$skillManifestPath = Join-Path $Candidate 'SKILL.md'
if (-not (Test-Path -LiteralPath $skillManifestPath -PathType Leaf)) {
throw 'Installed D-AI Skill root is invalid: SKILL.md is missing'
}
$skillManifest = Get-Content -LiteralPath $skillManifestPath -Raw
if ($skillManifest -notmatch '(?m)^name:\s*d-ai\s*$') {
throw 'Installed D-AI Skill root is invalid: SKILL.md is not the d-ai Skill'
}
foreach ($scriptName in @('invoke.ps1', 'set-runtime-binding.ps1')) {
if (-not (Test-Path -LiteralPath (Join-Path $Candidate "scripts\\$scriptName") -PathType Leaf)) {
throw "Installed D-AI Skill root is invalid: scripts/$scriptName is missing"
}
}
}

$skillItem = Get-Item -LiteralPath $SkillRoot -Force
Assert-FullyQualifiedPath $SkillRoot 'Installed D-AI Skill root'
if (-not $skillItem.PSIsContainer) {
throw "Installed D-AI Skill root is not a directory: $SkillRoot"
}
$resolvedSkillRoot = $skillItem.FullName
Assert-InstalledSkillRoot $resolvedSkillRoot
$resolvedRuntimeRoot = Resolve-Directory $RuntimeRoot 'D-AI runtime root'
Assert-RuntimeRoot $resolvedRuntimeRoot
$bindingPath = Join-Path $resolvedSkillRoot '.runtime-root'
$existing = if (Test-Path -LiteralPath $bindingPath -PathType Leaf) { (Get-Content -LiteralPath $bindingPath -Raw).Trim() } else { $null }
if ($existing -eq $resolvedRuntimeRoot) {
[Console]::Out.WriteLine((([ordered]@{ status = 'unchanged'; bindingPath = $bindingPath; runtimeRoot = $resolvedRuntimeRoot } | ConvertTo-Json -Compress)))
exit 0
}

$temporaryPath = "$bindingPath.$([guid]::NewGuid().ToString('N')).tmp"
try {
[System.IO.File]::WriteAllText($temporaryPath, "$resolvedRuntimeRoot`r`n", [System.Text.UTF8Encoding]::new($false))
Move-Item -LiteralPath $temporaryPath -Destination $bindingPath -Force
Comment on lines +78 to +81

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Ignore the repository-local runtime binding

When the documented repository-local entry at skills/custom/d-ai/scripts/invoke.ps1 is configured by passing its own Skill root, this write creates skills/custom/d-ai/.runtime-root, but no ignore rule covers that machine-local file. Normal activation therefore leaves the canonical checkout dirty, which makes the documented sync path refuse to pull and contaminates subsequent release diffs; add a narrowly scoped ignore rule for the binding.

AGENTS.md reference: AGENTS.md:L28-L31

Useful? React with 👍 / 👎.

} finally {
if (Test-Path -LiteralPath $temporaryPath) {
Remove-Item -LiteralPath $temporaryPath -Force
}
}
[Console]::Out.WriteLine((([ordered]@{ status = if ($null -eq $existing) { 'created' } else { 'updated' }; bindingPath = $bindingPath; runtimeRoot = $resolvedRuntimeRoot } | ConvertTo-Json -Compress)))
Loading