Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
e485077
Preserve Roadmap display options
SIkebe Aug 25, 2026
04c909a
Remove obsolete compatibility paths
SIkebe Aug 25, 2026
2a4251f
Harden Roadmap display validation
SIkebe Aug 25, 2026
5e76dcf
Make Roadmap capture fail independently
SIkebe Aug 25, 2026
fb328d2
Validate required schema-v2 template state
SIkebe Aug 25, 2026
58de71b
Exercise rendered Roadmap output in shared E2E
SIkebe Aug 25, 2026
8892134
Add mixed-state Roadmap fixture coverage
SIkebe Aug 25, 2026
4e45bdb
Centralize Roadmap rendering selectors
SIkebe Aug 25, 2026
df3bd58
Count only visible Roadmap dates
SIkebe Aug 25, 2026
e42898a
Model Roadmap display options as shared state
SIkebe Aug 25, 2026
b2be781
Revert "Harden Roadmap display validation"
SIkebe Aug 25, 2026
52e07fc
Revert "Preserve Roadmap display options"
SIkebe Aug 25, 2026
e58b1fc
Document unsupported Roadmap display controls
SIkebe Aug 25, 2026
04e88ef
Reject incomplete schema-v2 snapshots
SIkebe Aug 25, 2026
6420d8d
Normalize malformed snapshot errors
SIkebe Aug 25, 2026
ca885b2
Require explicit schema-v2 state
SIkebe Aug 25, 2026
29a938f
Align schema-v2 documentation
SIkebe Aug 25, 2026
ebe404a
Reapply "Preserve Roadmap display options"
SIkebe Aug 26, 2026
974ee0e
Reapply "Harden Roadmap display validation"
SIkebe Aug 26, 2026
23a6953
Persist browser-only view settings across sessions
SIkebe Aug 26, 2026
be72928
Flush recoverable Roadmap writes
SIkebe Aug 26, 2026
357ab38
Keep profile persistence regression lightweight
SIkebe Aug 26, 2026
6afd0c1
Verify Roadmap display controls independently
SIkebe Aug 26, 2026
dbb2ec6
Validate Roadmap state before import writes
SIkebe Aug 26, 2026
591168a
Target Roadmap pills in rendering checks
SIkebe Aug 26, 2026
1a05ea2
Restore browser profile after E2E drift
SIkebe Aug 26, 2026
d5c225c
Describe all retained E2E drifts
SIkebe Aug 26, 2026
2b3a106
Test partial Roadmap state persistence
SIkebe Aug 26, 2026
cbd23e6
Gate Roadmap rendering fixture before import
SIkebe Aug 26, 2026
93dbfd7
Retry delayed field default persistence
SIkebe Aug 27, 2026
89d6fb8
Explain live API failures on pull requests
SIkebe Aug 28, 2026
de680e4
Isolate live API failure reporting
SIkebe Aug 28, 2026
b8e8df6
Fix trusted reporting and fixture guidance
SIkebe Aug 28, 2026
6e12dd7
Sanitize integration test names in PR comments
SIkebe Aug 28, 2026
673c6f5
Keep reusable live API workflow read-only
SIkebe Aug 28, 2026
af78fe7
Scope reporter token to individual steps
SIkebe Aug 28, 2026
c9f39af
Warn before using undocumented Roadmap UI
SIkebe Aug 28, 2026
5c58cee
Isolate live API comments by commit
SIkebe Aug 28, 2026
6c8d5ed
Serialize live API status comments per PR
SIkebe Aug 28, 2026
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
61 changes: 52 additions & 9 deletions .github/skills/ghpmv-e2e-validation/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ agent が terminal に command を直接入力できず、ユーザー自身が
| browser-e2e field-sum status | `fixture-pending`, `snapshot-match`, `target-view-match`, `target-render-observed`, `drift-detected`, `repair-match` |
| browser-e2e field-default contract | `Fixture Text=既定値 🌏`, `Fixture Number=-7`, `Fixture Number 2=0`, `Fixture Select=Beta` |
| browser-e2e field-default status | `fixture-pending`, `snapshot-match`, `target-field-match`, `new-draft-observed`, `drift-detected`, `repair-match` |
| browser-e2e Roadmap display contract | `Fixture Roadmap: truncateTitles=true, showDateFields=true` |
| browser-e2e Roadmap display status | `fixture-pending`, `snapshot-match`, `target-view-match`, `target-render-observed`, `drift-detected`, `repair-match` |
| resource inventory | この run が作成した Project / repository の side、name、URL / number、作成 Step、cleanup 状態 |

`browser-e2e` の既存 round-trip は次の field-sum contract も常に検証する。別 scenario には分岐させず、settings に重複保存しない。
Expand All @@ -205,6 +207,8 @@ required Number fields は `Fixture Number` と `Fixture Number 2`。source / ta

同じ round-trip で field defaults も常に検証する。`setup --fixture --fixture-ui` は source items 作成後に defaults を設定するため既存 item values を変更しない。Step 6 は typed defaults を snapshot から検査し、Step 10 は `Field: Match` 後に `--fixture-field-default-check` で disposable target draft への自動入力を機械確認する。drift phase は `--fixture-field-default-drift` で Text / zero Number / Single-select を変更し、negative Number default を clear した後、既存の一回の repair import で Field sum と同時に戻す。

同じ `Fixture Roadmap` で `truncateTitles=true` と `showDateFields=true` も常に検証する。Step 6 は両 property が boolean として capture されたことを確認し、初回 browser-assisted verify は `View: Match` を要求する。negative-test phase では `setup --fixture-roadmap-display-drift` が `Show date fields=true` を維持したまま `Truncate titles=false` だけを設定し、property の独立性を確認してから、Field default / Field sum と同じ一回の repair import で戻す。別 scenario や別 target は作らない。

## Feature checkpoint の実行時間最小化

Issue ごとの機能検証を追加するときも、user-facing scenario selector や独立した full round trip を増やさない。次へ統合する。
Expand Down Expand Up @@ -1100,12 +1104,20 @@ foreach ($expected in $expectedViews) {
}
Write-Output ("GHPMV_FIELD_SUM_VIEW:{0}:{1}" -f $expected.Name, ($actualFieldSum -join ', '))
}
$roadmap = @($snapshot.views | Where-Object name -eq 'Fixture Roadmap')
if ($roadmap.Count -ne 1 -or
$roadmap[0].ui.roadmap.truncateTitles -ne $true -or
$roadmap[0].ui.roadmap.showDateFields -ne $true) {
Stop-FieldSumSnapshotCheck 'Fixture Roadmap must capture truncateTitles=true and showDateFields=true.'
return
}
Write-Output 'GHPMV_ROADMAP_DISPLAY_SNAPSHOT_MATCH'
Write-Output 'GHPMV_FIELD_SUM_SNAPSHOT_MATCH'
Write-Output 'GHPMV_FIELD_DEFAULT_SNAPSHOT_MATCH'
$global:LASTEXITCODE = 0
```

`GHPMV_FIELD_DEFAULT_SNAPSHOT_MATCH`、`GHPMV_FIELD_SUM_SNAPSHOT_MATCH`、command exit code 0 をすべて確認した場合だけ両 feature status を `snapshot-match` とし、先へ進む。zero は null と区別し、Single-select は source option ID でなく `singleSelectOptionName=Beta` を要求する。Table / Roadmap のいずれかだけ一致、warning、missing UI、`1 more` のような summary text、`null` と空集合以外の不一致を成功扱いしない。失敗時は source fixture contract の実値を示し、新しい標準 fixture を作るかどうかを一問で確認して停止する。
`GHPMV_FIELD_DEFAULT_SNAPSHOT_MATCH`、`GHPMV_FIELD_SUM_SNAPSHOT_MATCH`、`GHPMV_ROADMAP_DISPLAY_SNAPSHOT_MATCH`、command exit code 0 をすべて確認した場合だけ各 feature status を `snapshot-match` とし、先へ進む。zero は null と区別し、Single-select は source option ID でなく `singleSelectOptionName=Beta` を要求する。Table / Roadmap のいずれかだけ一致、warning、missing UI、`1 more` のような summary text、`null` と空集合以外の不一致を成功扱いしない。失敗時は source fixture contract の実値を示し、新しい標準 fixture を作るかどうかを一問で確認して停止する。

`api-only` / `browser-e2e`では、target PAT入力またはtarget resource準備より前に同じterminalでsnapshot-driven capabilityを算出する。

Expand Down Expand Up @@ -1532,7 +1544,7 @@ finally {
}
```

target が data residency の場合は `--api-base-url <target-api-url>` と `--browser-base-url <target-web-url>` を追加する。command は `View 1` と `Fixture Roadmap` を reload し、visible group header、`Count` rendering、各 Number field の numeric aggregate label DOM で検査する。両 View の `Rendered Field sums verified`、`Fixture field-sum rendering verified: ... views=2`、command exit code 0 を確認した場合だけ `browser-e2e field-sum status=target-render-observed` として deliberate drift へ進む。欠落は非ゼロ終了にし、対話用質問で補完しない。
target が data residency の場合は `--api-base-url <target-api-url>` と `--browser-base-url <target-web-url>` を追加する。command は `View 1` と `Fixture Roadmap` を reload し、visible group header、`Count` rendering、各 Number field の numeric aggregate label に加え、Roadmap の長い title が実際に clip/ellipsis され、date field が同じ item に描画されることを DOM で検査する。両 View の `Rendered Field sums verified`、`Fixture field-sum rendering verified: ... views=2`、command exit code 0 を確認した場合だけ Field sum と Roadmap display の status を `target-render-observed` として deliberate drift へ進む。欠落は非ゼロ終了にし、対話用質問で補完しない。

### Deliberate drift と repair

Expand Down Expand Up @@ -1577,7 +1589,27 @@ finally {
}
```

target が data residency の場合は `--api-base-url <target-api-url>` と `--browser-base-url <target-web-url>` を追加する。`Fixture field-sum drift applied`、`viewWarnings=0`、command exit code 0 を確認した後、同じ terminal で次の drift verify command を送る。placeholder、optional mapping、profile、endpoint は初回 verify と同じ実値へ置き換える。この command は native exit code 0 を失敗とし、非ゼロ終了かつ report の View category が `Mismatch`、`field sum mismatch` が存在する場合だけ semantic success とする。
target が data residency の場合は `--api-base-url <target-api-url>` と `--browser-base-url <target-web-url>` を追加する。`Fixture field-sum drift applied`、`viewWarnings=0`、command exit code 0 を確認した後、同じ target に Roadmap display drift を適用する。

```powershell
$previousGhpmvToken = $env:GHPMV_TOKEN
$previousGitHubToken = $env:GITHUB_TOKEN
try {
$env:GHPMV_TOKEN = $env:TARGET_TOKEN
Remove-Item Env:GITHUB_TOKEN -ErrorAction SilentlyContinue
dotnet run --project src\Ghpmv.Cli -c Release --no-build -- setup `
--fixture-roadmap-display-drift `
--fixture-org <target-org> `
--fixture-project <target-project-number> `
--browser-profile target
}
finally {
if ($null -eq $previousGhpmvToken) { Remove-Item Env:GHPMV_TOKEN -ErrorAction SilentlyContinue } else { $env:GHPMV_TOKEN = $previousGhpmvToken }
if ($null -eq $previousGitHubToken) { Remove-Item Env:GITHUB_TOKEN -ErrorAction SilentlyContinue } else { $env:GITHUB_TOKEN = $previousGitHubToken }
}
```

target が data residency の場合は同じ endpoint option を追加する。`Fixture Roadmap display drift applied`、`viewWarnings=0`、command exit code 0 を確認した後、次の drift verify command を送る。placeholder、optional mapping、profile、endpoint は初回 verify と同じ実値へ置き換える。この command は native exit code 0 を失敗とし、非ゼロ終了かつ report の View category が `Mismatch`、field sum と `truncate titles` mismatch が存在し、`show date fields` mismatch が存在しない場合だけ semantic success とする。

```powershell
function Stop-FieldSumDriftCheck([string]$Message) {
Expand Down Expand Up @@ -1617,6 +1649,12 @@ $driftFieldCategories = @($driftReport.categories | Where-Object category -eq 'F
$driftViewCategories = @($driftReport.categories | Where-Object category -eq 'View')
$fieldDefaultDifferences = @($driftReport.differences | Where-Object { $_.category -eq 'Field' -and $_.message -match 'default value mismatch' })
$fieldSumDifferences = @($driftReport.differences | Where-Object { $_.category -eq 'View' -and $_.message -match "view 'View 1': field sum mismatch" })
$roadmapTitleDifferences = @($driftReport.differences | Where-Object {
$_.category -eq 'View' -and $_.message -match "view 'Fixture Roadmap': truncate titles mismatch"
})
$roadmapDateDifferences = @($driftReport.differences | Where-Object {
$_.category -eq 'View' -and $_.message -match "view 'Fixture Roadmap': show date fields mismatch"
})
$nonInfoDifferences = @($driftReport.differences | Where-Object severity -ne 'Info')
$unexpectedCategoryStatuses = @($driftReport.categories | Where-Object {
$_.category -notin @('Field', 'View') -and $_.status -notin @('Match', 'NotApplicable')
Expand All @@ -1627,19 +1665,23 @@ if ($driftFieldCategories.Count -ne 1 -or
$driftViewCategories.Count -ne 1 -or
$driftViewCategories[0].status -ne 'Mismatch' -or
$fieldSumDifferences.Count -ne 1 -or
$nonInfoDifferences.Count -ne 5 -or
$roadmapTitleDifferences.Count -ne 1 -or
$roadmapDateDifferences.Count -ne 0 -or
$nonInfoDifferences.Count -ne 6 -or
$unexpectedCategoryStatuses.Count -ne 0) {
Stop-FieldSumDriftCheck 'Verify did not contain exactly four Field default mismatches and the expected View 1 field-sum mismatch.'
Stop-FieldSumDriftCheck 'Verify did not contain exactly four Field default mismatches, the View 1 field-sum mismatch, and only the Fixture Roadmap title-truncation mismatch.'
return
}
Write-Output $fieldDefaultDifferences.message
Write-Output $fieldSumDifferences.message
Write-Output $roadmapTitleDifferences.message
Write-Output 'GHPMV_FIELD_DEFAULT_DRIFT_DETECTED'
Write-Output 'GHPMV_FIELD_SUM_DRIFT_DETECTED'
Write-Output 'GHPMV_ROADMAP_DISPLAY_DRIFT_DETECTED'
$global:LASTEXITCODE = 0
```

target が data residency の場合は、この drift verify にも初回 verify と同じ `--target-base-url <target-api-url>` と `--browser-base-url <target-web-url>` を追加する。`GHPMV_FIELD_DEFAULT_DRIFT_DETECTED`、`GHPMV_FIELD_SUM_DRIFT_DETECTED`、wrapper exit code 0 を確認した場合だけ両 feature status=`drift-detected` とする。
target が data residency の場合は、この drift verify にも初回 verify と同じ `--target-base-url <target-api-url>` と `--browser-base-url <target-web-url>` を追加する。3つの drift marker と wrapper exit code 0 を確認した場合だけ各 feature status=`drift-detected` とする。

続けて同じ snapshot と target Project へ browser-assisted import を再実行する。`--project-number` は既存 Project を常に更新するため、`--on-conflict` や `--project-title` を追加しない。

Expand Down Expand Up @@ -1747,10 +1789,11 @@ if ($global:GHPMV_REPAIR_VERIFY_EXIT_CODE -eq 0 -or
Write-Output 'GHPMV_ITEM_VALUES_REPAIR_MATCH'
Write-Output 'GHPMV_FIELD_DEFAULT_REPAIR_MATCH'
Write-Output 'GHPMV_FIELD_SUM_REPAIR_MATCH'
Write-Output 'GHPMV_ROADMAP_DISPLAY_REPAIR_MATCH'
$global:LASTEXITCODE = 0
```

target が data residency の場合は repair import / verify にも初回と同じ endpoint option を追加する。`GHPMV_FIELD_DEFAULT_REPAIR_MATCH`、`GHPMV_FIELD_SUM_REPAIR_MATCH`、command exit code 0 を確認後、次のfunctional checkを同じterminalへ送る。
target が data residency の場合は repair import / verify にも初回と同じ endpoint option を追加する。Field default / Field sum / Roadmap display の3つの repair marker と command exit code 0 を確認後、次のfunctional checkを同じterminalへ送る。

```powershell
$previousGhpmvToken = $env:GHPMV_TOKEN
Expand All @@ -1770,9 +1813,9 @@ finally {
}
```

target が data residency の場合は `--api-base-url <target-api-url>` と `--browser-base-url <target-web-url>` を追加する。`Fixture field defaults functionally verified: ... fields=4 draft=<id> title='<title>' cleanup=pending` と exit code 0 を確認し、修復後draftをnested resource inventoryへ`created`として追加する。修復後の new draftにも4 defaultsが入り、`GHPMV_ITEM_VALUES_REPAIR_MATCH`が既知のinventory draft以外にItem差分がないことを証明した場合、追加の対話用質問を行わず両 feature status=`repair-match` とする。
target が data residency の場合は `--api-base-url <target-api-url>` と `--browser-base-url <target-web-url>` を追加する。`Fixture field defaults functionally verified: ... fields=4 draft=<id> title='<title>' cleanup=pending` と exit code 0 を確認し、修復後draftをnested resource inventoryへ`created`として追加する。修復後の new draftにも4 defaultsが入り、`GHPMV_ITEM_VALUES_REPAIR_MATCH`が既知のinventory draft以外にItem差分がないことを証明した場合、追加の対話用質問を行わず3 feature status=`repair-match` とする。

`browser-e2e` は field-defaultの`new-draft-observed` / `repair-match`field-sumの`target-render-observed` / `repair-match`へ到達してから Resource inventory の cleanup 同意へ進む。`api-only` は通常の Step 10 完了後に cleanup 同意へ進む。
`browser-e2e` は field-defaultの`new-draft-observed` / `repair-match`field-sumとRoadmap displayの`target-render-observed` / `repair-match`へ到達してから Resource inventory の cleanup 同意へ進む。`api-only` は通常の Step 10 完了後に cleanup 同意へ進む。

## Troubleshooting

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ Tokens are resolved from `--token`, then the `GITHUB_TOKEN` / `GHPMV_TOKEN` envi

| Category | Verification coverage |
|---|---|
| Project | Description, README, visibility, closed state, and organization template state. A changed title is informational because import supports title overrides. Legacy snapshots without `project.template` preserve and do not compare the target template state. |
| Project | Description, README, visibility, closed state, and organization template state. A changed title is informational because import supports title overrides. |
| Field | Field presence/type, select option order/name/color/description, Issue Field description/visibility/linkage, and iteration dates/durations. |
| Item | Counts/types, issue and pull request identity, draft body, field values (including Project and Issue Field multi-select values), active-item order, and archived state. Archived-item order is excluded because GitHub cannot restore it. |
| StatusUpdate | History order, body (including the imported attribution note), status, start date, and target date. |
Expand Down
4 changes: 2 additions & 2 deletions docs/BROWSER_AUTOMATION_PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ GraphQL と Playwright を組み合わせた View・Workflow 移行の詳細設
| sort(複数キー+方向) | GraphQL `sortByFields`(`ProjectV2SortByField.direction`) | **UI** | |
| **Slice by** | ❌ API に無い → **UI で読む** | **UI** | |
| **Field sum** | ❌ API に無い → **UI で読む** | **UI** | Board と grouped Table / Roadmap。Count、複数 Number field、空集合を complete-set 同期 |
| **Roadmap 設定(Dates / Zoom / Markers)** | ❌ API に無い → **UI で読む** | **UI** | |
| タブの並び順 | **UI**(`navigation "Select view"` 内のsaved tab `href`順) | **UI**(タブの drag & drop) | GraphQL `POSITION`は現行UIのsaved-tab順と乖離する場合がある。`ViewSnapshot.tabPosition`はschema v1のnullable additive field |
| **Roadmap 設定(Dates / Zoom / Markers / Truncate titles / Show date fields)** | ❌ API に無い → **UI で読む** | **UI** | 2つの表示 option は boolean として独立に同期 |
| タブの並び順 | **UI**(`navigation "Select view"` 内のsaved tab `href`順) | **UI**(タブの drag & drop) | GraphQL `POSITION`は現行UIのsaved-tab順と乖離する場合がある |

### Workflow のプロパティ別ソースマップ

Expand Down
Loading