Files
2026-08-24 09:45:51 +02:00

97 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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
<details><summary>15 previous messages</summary>
> 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.
>
> <details><summary>Ran a command</summary>
>
> - Ran `Get-ChildItem -Force | Select-Object Mode,Length,LastWriteTime,Name; rg --files -g 'AGENTS.md' -g '*.md' -g '*.txt' -g '*.docx' -g '*.pdf'`
>
> </details>
>
> 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.
>
> <details><summary>Ran 3 commands</summary>
>
> - 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]`
>
> </details>
>
> 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.
>
> <details><summary>Ran a command</summary>
>
> - 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 }`
>
> </details>
>
> 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.
>
> <details><summary>Ran 3 commands</summary>
>
> - 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`
>
> </details>
>
> 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.
>
> <details><summary>Created 3 files, edited a file, ran a command</summary>
>
> - 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)
>
> </details>
>
> 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.
>
> <details><summary>Ran 4 commands</summary>
>
> - 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.' }`
>
> </details>
>
> 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.
>
> <details><summary>Edited 2 files, ran a command</summary>
>
> - 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``
>
> </details>
</details>
Implemented the complete workflow.
- Added the repository-local skill: [SKILL.md](<./.agents/skills/elixforms-schema-bulk-updater/SKILL.md:1>)
- Created the executable launcher: [Invoke-ElixFormsMetadataBulkUpdate.ps1](<./Invoke-ElixFormsMetadataBulkUpdate.ps1:1>)
- 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:
```powershell
.\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.