Files
elixforms-schema-bulk-updater/prompt-history.md
T
2026-08-24 09:45:51 +02:00

13 KiB
Raw Blame History

Add skills and PowerShell script

given the flow described in "User Workflow" secion of the document, and considering the whole document for a more detailed description, I want you to:

  • add appropriate skills
  • create a Powershell script that does what is described
15 previous messages

Ill inspect the workspace instructions and locate the documents “User Workflow” section first. Then Ill translate the full specification into the appropriate Codex skills and a PowerShell implementation, with runnable verification.

Ran a command
  • Ran Get-ChildItem -Force | Select-Object Mode,Length,LastWriteTime,Name; rg --files -g 'AGENTS.md' -g '*.md' -g '*.txt' -g '*.docx' -g '*.pdf'

The request includes creating reusable skills, so Im applying the skill-creator guidance before making changes. I found the specification in save-metadata-schema-automatic.md; Ill read it in full, including its workflow and validation requirements.

Ran 3 commands
  • Ran Get-Content -Raw 'C:\Users\pierp\.codex\skills\.system\skill-creator\SKILL.md'; Get-Content -Raw '.\save-metadata-schema-automatic.md'
  • Ran $lines = Get-Content '.\save-metadata-schema-automatic.md'; "LINES=$($lines.Count)"; rg -n '^#{1,4} ' '.\save-metadata-schema-automatic.md'
  • Ran $lines = Get-Content '.\save-metadata-schema-automatic.md'; $lines[0..493]

The specification is precise about request construction, but the save payload is the fragile part. Im checking the supplied HAR structurally—without printing session cookies—to reproduce the real multipart field format, headers, and response behavior instead of guessing from prose.

Ran a command
  • Ran $har = Get-Content -Raw '.\save-metadata-schema.har' | ConvertFrom-Json -Depth 100; $entries = @($har.log.entries | Where-Object { $_.request.url -match '/AJSRV/metadata/(list|search|save)' }); foreach ($entry in $entries) { $request = $entry.request; $safeHeaders = @($request.headers | Where-Object { $_.name -notmatch '^(Cookie|Authorization)$' } | Select-Object name,value); [pscustomobject]@{ Method=$request.method; Url=$request.url; Headers=$safeHeaders; PostMime=$request.postData.mimeType; Params=$request.postData.params; Text=$request.postData.text; Status=$entry.response.status; ResponseMime=$entry.response.content.mimeType } | ConvertTo-Json -Depth 20 }

The HAR reveals one important correction to the prose: save field names use the rows generic-schema/data ID (the second search column, e.g. 81825), not the first ID_OBJECT value. Ill encode that verified invariant in both the script and the reusable skill. The script will also preserve column order, fetch every result page, back up all search responses before any write, require an explicit destructive confirmation, and summarize per-row outcomes.

Ran 3 commands
  • Ran Get-Content -Raw 'C:\Users\pierp\.codex\skills\.system\skill-creator\references\openai_yaml.md'; git status --short
  • Ran python 'C:\Users\pierp\.codex\skills\.system\skill-creator\scripts\init_skill.py' elixforms-schema-bulk-updater --path '.\.agents\skills' --resources scripts,references --interface 'display_name=ElixForms Metadata Bulk Update' --interface 'short_description=Safely update one metadata field in bulk' --interface 'default_prompt=Use $elixforms-schema-bulk-updater to prepare or run a guarded ElixForms metadata bulk update.'
  • Ran Get-Content -Raw '.\.agents\skills\elixforms-schema-bulk-updater\SKILL.md'; Get-Content -Raw '.\.agents\skills\elixforms-schema-bulk-updater\agents\openai.yaml'; Get-ChildItem -Recurse '.\.agents\skills\elixforms-schema-bulk-updater' | Select-Object FullName

Ive finished the design pass. The skill will be repository-local and self-contained under .agents/skills, with the full PowerShell implementation packaged as its deterministic helper plus a short root launcher. No credentials will be persisted; backups contain search data and filters but never the cookie.

The initial patch hit a patch-tool constraint while replacing the generated scaffold; no implementation files were partially written. Im splitting the change into smaller atomic patches and continuing.

Created 3 files, edited a file, ran a command
  • Wrote ./.agents/skills/elixforms-schema-bulk-updater/SKILL.md (+20 -6)
  • Wrote ./.agents/skills/elixforms-schema-bulk-updater/references/protocol.md (+37 -0)
  • Wrote ./Invoke-ElixFormsMetadataBulkUpdate.ps1 (+1 -0)
  • Ran Get-Content -Raw '.\.agents\skills\elixforms-schema-bulk-updater\SKILL.md'; Test-Path '.\.agents\skills\elixforms-schema-bulk-updater\references\protocol.md'; Test-Path '.\Invoke-ElixFormsMetadataBulkUpdate.ps1'
  • Wrote ./.agents/skills/elixforms-schema-bulk-updater/scripts/Invoke-ElixFormsMetadataBulkUpdate.ps1 (+653 -0)

The implementation is now in place. Im at the verification stage: parsing it with PowerShells AST parser, exercising URI encoding and multipart byte construction against the documented examples, checking the root launcher, and validating the skill package for unfinished scaffold content or metadata errors.

Ran 4 commands
  • Ran $scriptPath = Resolve-Path '.\.agents\skills\elixforms-schema-bulk-updater\scripts\Invoke-ElixFormsMetadataBulkUpdate.ps1'; $tokens = $null; $parseErrors = $null; $ast = [System.Management.Automation.Language.Parser]::ParseFile($scriptPath, [ref]$tokens, [ref]$parseErrors); if ($parseErrors.Count -gt 0) { $parseErrors | Format-List; exit 1 }; 'PowerShell parse: OK'; . $scriptPath; $query = [ordered]@{'SEARCH_IN[]'=616; 'S_616_NEW_COL0014'='antani tapioca'; PAGE=1; AJL='it'; PAGESIZE=80; SECURE='true'}; $uri = New-ElixFormsUri -BaseUri 'https://console-unipr.elixforms.it/AJSRV/metadata' -Route 'search' -Query $query; "URI=$uri"; if ($uri.AbsoluteUri -notmatch 'SEARCH_IN%5B%5D=616' -or $uri.AbsoluteUri -notmatch 'antani%20tapioca') { throw 'Query encoding test failed.' }; $multipart = New-MultipartFieldBody -Name 'S_616_81825_COL0014' -Value ''; $multipartText = [Text.Encoding]::UTF8.GetString($multipart.Bytes); if ($multipartText -notmatch 'name="S_616_81825_COL0014"' -or -not $multipartText.EndsWith("--`r`n")) { throw 'Multipart test failed.' }; "Multipart bytes=$($multipart.Bytes.Length) content-type=$($multipart.ContentType)"; 'Helper tests: OK'; python 'C:\Users\pierp\.codex\skills\.system\skill-creator\scripts\quick_validate.py' '.\.agents\skills\elixforms-schema-bulk-updater'; rg -n '\[TODO|TODO:' '.\.agents\skills\elixforms-schema-bulk-updater' '.\Invoke-ElixFormsMetadataBulkUpdate.ps1'
  • Ran $scriptPath = Resolve-Path '.\.agents\skills\elixforms-schema-bulk-updater\scripts\Invoke-ElixFormsMetadataBulkUpdate.ps1'; $search = Get-Content -Raw '.\search-schema-results.json' | ConvertFrom-Json; "Fixture columns=$(@($search.columns).Count) rows=$(@($search.data).Count) total=$($search.totalRecords) pages=$($search.numPages)"; $genericKey = 'S_616_ID_GENERICSCHEMA'; $genericIndex = [Array]::IndexOf([object[]]@($search.columns.key), $genericKey); $objectIndex = [Array]::IndexOf([object[]]@($search.columns.key), 'ID_OBJECT'); "Fixture ID indexes: object=$objectIndex generic-data=$genericIndex"; if ($genericIndex -lt 0 -or $objectIndex -lt 0) { throw 'Fixture identifier columns missing.' }; $firstRow = @($search.data)[0]; "First save-name example=S_616_$($firstRow[$genericIndex])_COL0014 (object $($firstRow[$objectIndex]))"; if (Get-Command Invoke-ScriptAnalyzer -ErrorAction SilentlyContinue) { Invoke-ScriptAnalyzer -Path $scriptPath -Severity Warning,Error | Format-Table -AutoSize } else { 'PSScriptAnalyzer not installed; skipped.' }; if (Get-Command powershell.exe -ErrorAction SilentlyContinue) { powershell.exe -NoProfile -Command "`$tokens=`$null; `$errors=`$null; [System.Management.Automation.Language.Parser]::ParseFile('$($scriptPath.Path.Replace("'", "''"))',[ref]`$tokens,[ref]`$errors) > `$null; if (`$errors.Count) { `$errors | Out-String; exit 1 }; 'Windows PowerShell parse: OK'" }
  • Ran $failed = $false; Get-ChildItem -Recurse -Filter '*.ps1' | ForEach-Object { $tokens=$null; $errors=$null; [System.Management.Automation.Language.Parser]::ParseFile($_.FullName,[ref]$tokens,[ref]$errors) > $null; if ($errors.Count) { $failed=$true; $errors | ForEach-Object { "PARSE ERROR $($_.Extent.File):$($_.Extent.StartLineNumber): $($_.Message)" } } else { "PARSE OK $($_.FullName)" } }; if ($failed) { exit 1 }; Get-ChildItem -Recurse '.\.agents\skills\elixforms-schema-bulk-updater' | Select-Object FullName,Length; Get-Content -Raw '.\.agents\skills\elixforms-schema-bulk-updater\agents\openai.yaml'
  • Ran try { throw 'Value {0}' -f 42 } catch { "THROW_TEST=$($_.Exception.Message)" }; . '.\.agents\skills\elixforms-schema-bulk-updater\scripts\Invoke-ElixFormsMetadataBulkUpdate.ps1'; $sample = Get-Content -Raw '.\search-schema-results.json' | ConvertFrom-Json; $columns = @($sample.columns); $rows = @($sample.data); "RowsRuntimeType=$($rows.GetType().FullName) FirstRowType=$($rows[0].GetType().FullName) FirstRowCount=$(@($rows[0]).Count)"; $objectIndex = Get-ColumnIndex -Columns $columns -Key 'ID_OBJECT'; $genericIndex = Get-ColumnIndex -Columns $columns -Key 'S_616_ID_GENERICSCHEMA'; "FunctionIndexes=$objectIndex,$genericIndex"; $schemaFixture = [pscustomobject]@{ sections = @([pscustomobject]@{key='SEC_B'; title='B'; orderKey='ORD002'; fields=@([pscustomobject]@{key='COL_B';title='B';type='STRING';orderKey='ORD001'})},[pscustomobject]@{key='SEC_A';title='A';orderKey='ORD001';fields=@([pscustomobject]@{key='COL_A2';title='A2';type='STRING';orderKey='ORD002'},[pscustomobject]@{key='COL_A1';title='A1';type='STRING';orderKey='ORD001'})})}; $ordered = @(Get-OrderedSchemaFields -Schema $schemaFixture); "OrderedFields=$($ordered.Key -join ',')"; if (($ordered.Key -join ',') -ne 'COL_A1,COL_A2,COL_B') { throw 'Field ordering test failed.' }

The verification checks are clean in both PowerShell 7 and Windows PowerShell 5.1, and the supplied 56-row fixture maps identifiers as expected. Im making one final hardening pass on backup naming and inline help, then Ill hand over the exact run command and the HAR-derived identifier caveat.

Edited 2 files, ran a command
  • Wrote ./.agents/skills/elixforms-schema-bulk-updater/scripts/Invoke-ElixFormsMetadataBulkUpdate.ps1 (+25 -1)
  • Wrote ./Invoke-ElixFormsMetadataBulkUpdate.ps1 (+5 -0)
  • Ran $allGood = $true; Get-ChildItem -Recurse -Filter '*.ps1' | ForEach-Object { $tokens=$null; $errors=$null; [System.Management.Automation.Language.Parser]::ParseFile($_.FullName,[ref]$tokens,[ref]$errors) > $null; if ($errors.Count) { $allGood=$false; $errors | Format-List } }; if (-not $allGood) { exit 1 }; . '.\.agents\skills\elixforms-schema-bulk-updater\scripts\Invoke-ElixFormsMetadataBulkUpdate.ps1'; $query=[ordered]@{'SEARCH_IN[]'=616;'S_616_NEW_COL0014'='antani tapioca';PAGE=1;AJL='it';PAGESIZE=80;SECURE='true'}; $uri=New-ElixFormsUri -BaseUri 'https://console-unipr.elixforms.it/AJSRV/metadata' -Route 'search' -Query $query; if ($uri.AbsoluteUri -notmatch 'SEARCH_IN%5B%5D=616' -or $uri.AbsoluteUri -notmatch 'antani%20tapioca') { throw 'URI test failed' }; $part=New-MultipartFieldBody -Name 'S_616_81825_COL0014' -Value ''; if ($part.Bytes.Length -le 0 -or $part.ContentType -notmatch '^multipart/form-data; boundary=') { throw 'Multipart test failed' }; python 'C:\Users\pierp\.codex\skills\.system\skill-creator\scripts\quick_validate.py' '.\.agents\skills\elixforms-schema-bulk-updater'; 'Final validation: OK'; rg -n '^function (Get-ElixFormsSearchResult|Save-SearchBackup|Invoke-ElixFormsMetadataBulkUpdate)|generic-schema/data ID|^Use `scripts' '.\.agents\skills\elixforms-schema-bulk-updater\SKILL.md' '.\.agents\skills\elixforms-schema-bulk-updater\references\protocol.md' '.\.agents\skills\elixforms-schema-bulk-updater\scripts\Invoke-ElixFormsMetadataBulkUpdate.ps1'; Get-ChildItem -Recurse -File '.\.agents\skills\elixforms-schema-bulk-updater','Invoke-ElixFormsMetadataBulkUpdate.ps1' | Select-Object FullName,Length

Implemented the complete workflow.

  • Added the repository-local skill: SKILL.md
  • Created the executable launcher: Invoke-ElixFormsMetadataBulkUpdate.ps1
  • Added protocol documentation, including the HAR-confirmed requirement to use ID_GENERICSCHEMA/dataId rather than ID_OBJECT when constructing save field names.

Run it with:

.\Invoke-ElixFormsMetadataBulkUpdate.ps1

The script includes hidden cookie input, schema validation, ordered filters, pagination, result preview, two confirmations, timestamped JSON backups, multipart saves with byte-accurate Content-Length, failure-safe stopping, summaries, and optional verification.

Validated with PowerShell 7 and Windows PowerShell 5.1 parsing, fixture-based identifier checks, URI/multipart tests, and the Codex skill validator. The live API was not called because that requires your authenticated cookie and would modify production data.