Store runs locally and enrich SteamKit reports

This commit is contained in:
seanbetts committed 2026-05-11 11:29:20 +01:00
1 parent 0fac3eb847
commit 692cef0abb
22 files changed
+1102 -109

No files matched your search

+4 -2
View File
@@ -15,10 +15,12 @@ auth/
*.state.json
*.storage.json
# Ad hoc run output if someone chooses to place it inside the repo
# Local run artifacts
/runs/
# Ad hoc scratch output if someone chooses to place it inside the repo
artifacts/
output/
runs/
tmp/
scratch/
+19 -9
View File
@@ -30,7 +30,14 @@ It is a repeatable evidence-gathering workflow for answering a narrow set of que
The normal entry point is the wrapper script:
```sh
scripts/run_watch.sh YYYY-MM-DD /path/to/run-output /path/to/SteamTracking
scripts/run_watch.sh YYYY-MM-DD
```
By default this writes ignored artifacts under `runs/YYYY-MM-DD` in this repo and uses `/tmp/SteamTracking-master`.
Pass explicit paths only when you want to override those defaults:
```sh
scripts/run_watch.sh YYYY-MM-DD /custom/run-base /path/to/SteamTracking
```
## Repository Layout
@@ -51,6 +58,7 @@ Important directories:
- `scripts/`: the runnable checks and report builders
- `references/`: source map, Komodo notes, evidence rubric
- `status/`: seeded baseline answer and run notes
- `runs/`: local gitignored run artifacts
## Dependencies
@@ -92,10 +100,10 @@ chmod +x scripts/*.sh
4. Run a watch pass:
```sh
scripts/run_watch.sh 2026-04-25 ~/steam_hardware_watch /tmp/SteamTracking-master
scripts/run_watch.sh 2026-04-25
```
This creates a dated run folder under `~/steam_hardware_watch/2026-04-25`.
This creates a dated run folder under `runs/2026-04-25`.
### Common Path
@@ -103,7 +111,7 @@ For the least disruptive Komodo flow, use the dedicated background browser boots
```sh
scripts/bootstrap_komodo.sh
scripts/run_watch.sh 2026-04-25 ~/steam_hardware_watch /tmp/SteamTracking-master
scripts/run_watch.sh 2026-04-25
scripts/close_komodo.sh
```
@@ -113,7 +121,7 @@ SteamDB can require the same live-browser treatment:
```sh
scripts/bootstrap_steamdb.sh
scripts/run_watch.sh 2026-04-25 ~/steam_hardware_watch /tmp/SteamTracking-master
scripts/run_watch.sh 2026-04-25
scripts/close_steamdb.sh
```
@@ -146,13 +154,13 @@ chmod 600 .local/steamkit-env.sh
Then run either the source directly:
```sh
scripts/check_steamkit_pics.sh ~/steam_hardware_watch/2026-05-11
scripts/check_steamkit_pics.sh runs/2026-05-11
```
or the normal watcher:
```sh
scripts/run_watch.sh 2026-05-11 ~/steam_hardware_watch /tmp/SteamTracking-master
scripts/run_watch.sh 2026-05-11
```
Outputs:
@@ -160,6 +168,7 @@ Outputs:
- `RUN_DIR/api/steamkit/pics-product-info.json`
- `RUN_DIR/reports/steamkit-pics-packages.tsv`
- `RUN_DIR/reports/steamkit-pics-key-lines.txt`
- `RUN_DIR/reports/steamkit-pics-detail.md`
- `RUN_DIR/reports/steamkit-pics-errors.txt`
If the env file is missing, the script writes a non-fatal `missing_credentials` report so the normal watcher still completes. Do not use your main Steam account, do not poll aggressively, and do not extend this helper to protected depot downloads.
@@ -179,6 +188,7 @@ Each run writes:
- `blocked-visual-assets.tsv`
- `manual-asset-urls.txt`
- `steamkit-pics-packages.tsv`
- `steamkit-pics-detail.md`
- `steamvr-depots-key-lines.txt`
- `steamos-mirror-key-lines.txt`
@@ -262,7 +272,7 @@ If Komodo needs any manual interaction, switch to that dedicated window when con
Then run:
```sh
scripts/run_watch.sh 2026-04-25 ~/steam_hardware_watch /tmp/SteamTracking-master
scripts/run_watch.sh 2026-04-25
```
`check_komodo.sh` will automatically pick up `.local/komodo-env.sh` when present.
@@ -374,7 +384,7 @@ If SteamDB needs manual interaction, switch to that dedicated Chrome window, com
Then run:
```sh
scripts/run_watch.sh 2026-04-25 ~/steam_hardware_watch /tmp/SteamTracking-master
scripts/run_watch.sh 2026-04-25
```
`check_steamdb.sh` automatically picks up `.local/steamdb-env.sh` when present. `run_watch.sh` auto-closes the dedicated SteamDB browser at the end unless you set:
+4 -2
View File
@@ -58,6 +58,8 @@ Use the source helpers when available:
- [scripts/save_visual_assets.py](scripts/save_visual_assets.py)
- [scripts/draft_status_update.py](scripts/draft_status_update.py)
Default run artifacts live under the repo-local gitignored [runs](runs) directory. Use an explicit base directory only when the user asks to store artifacts elsewhere.
Asset discovery should be dynamic:
- discover from current-run Komodo metadata when available
@@ -137,7 +139,7 @@ Use a narrow SteamKit2 helper when available. It should:
- load credentials from `.local/steamkit-env.sh` or equivalent environment variables
- poll only watched Valve hardware app and package IDs
- save raw app/package product-info snapshots and changenumbers
- write `steamkit-pics-packages.tsv` and `steamkit-pics-key-lines.txt`
- write `steamkit-pics-packages.tsv`, `steamkit-pics-key-lines.txt`, and `steamkit-pics-detail.md`
- compare snapshots against the previous run
- avoid protected depot downloads and aggressive polling
@@ -361,5 +363,5 @@ It will:
Example:
```sh
~/.codex/skills/steam-hardware-watch/scripts/run_watch.sh 2026-04-25 ~/steam_hardware_watch /tmp/SteamTracking-master
~/.codex/skills/steam-hardware-watch/scripts/run_watch.sh 2026-04-25
```
+1
View File
@@ -59,6 +59,7 @@ Local helper:
- raw snapshot: `RUN_DIR/api/steamkit/pics-product-info.json`
- normalized package/app report: `RUN_DIR/reports/steamkit-pics-packages.tsv`
- summary lines: `RUN_DIR/reports/steamkit-pics-key-lines.txt`
- human-readable detail report: `RUN_DIR/reports/steamkit-pics-detail.md`
Operational constraints:
+71 -20
View File
@@ -17,9 +17,31 @@ mkdir -p "$OUT_DIR" "$REPORT_DIR"
ERROR_FILE="$REPORT_DIR/steamkit-pics-errors.txt"
REPORT_FILE="$REPORT_DIR/steamkit-pics-packages.tsv"
KEY_LINES_FILE="$REPORT_DIR/steamkit-pics-key-lines.txt"
DETAIL_REPORT_FILE="$REPORT_DIR/steamkit-pics-detail.md"
: > "$ERROR_FILE"
: > "$REPORT_FILE"
: > "$KEY_LINES_FILE"
: > "$DETAIL_REPORT_FILE"
find_previous_report() {
current_base="$(basename "$RUN_DIR")"
base_dir="$(dirname "$RUN_DIR")"
previous_dir=""
for candidate in $(find "$base_dir" -mindepth 1 -maxdepth 1 -type d -name '????-??-??' | sort); do
if [ "$candidate" = "$RUN_DIR" ]; then
continue
fi
candidate_base="$(basename "$candidate")"
if [ "$candidate_base" \< "$current_base" ]; then
previous_dir="$candidate"
fi
done
if [ -n "$previous_dir" ] && [ -s "$previous_dir/reports/steamkit-pics-packages.tsv" ]; then
printf '%s\n' "$previous_dir/reports/steamkit-pics-packages.tsv"
fi
}
load_local_env() {
env_file="${STEAMKIT_ENV_FILE:-$REPO_DIR/.local/steamkit-env.sh}"
@@ -33,17 +55,17 @@ write_unavailable_report() {
reason="$1"
detail="$2"
{
printf '%s\n' "type product id status changenumber related_ids details"
printf '%s\n' "app Steam Controller 4165870 $reason $detail"
printf '%s\n' "app Steam Frame 4165890 $reason $detail"
printf '%s\n' "app Steam Machine 4165910 $reason $detail"
printf '%s\n' "package Steam Controller 1558609 $reason $detail"
printf '%s\n' "package Steam Machine 1629446 $reason $detail"
printf '%s\n' "package Steam Machine 1629447 $reason $detail"
printf '%s\n' "package Steam Machine 1629458 $reason $detail"
printf '%s\n' "package Steam Machine 1629460 $reason $detail"
printf '%s\n' "package Steam Frame 1629484 $reason $detail"
printf '%s\n' "package Steam Frame 1629486 $reason $detail"
printf '%s\n' "type product id status changenumber previous_changenumber changed_since_previous sha_hash only_public name related_ids details"
printf '%s\n' "app Steam Controller 4165870 $reason $detail"
printf '%s\n' "app Steam Frame 4165890 $reason $detail"
printf '%s\n' "app Steam Machine 4165910 $reason $detail"
printf '%s\n' "package Steam Controller 1558609 $reason $detail"
printf '%s\n' "package Steam Machine 1629446 $reason $detail"
printf '%s\n' "package Steam Machine 1629447 $reason $detail"
printf '%s\n' "package Steam Machine 1629458 $reason $detail"
printf '%s\n' "package Steam Machine 1629460 $reason $detail"
printf '%s\n' "package Steam Frame 1629484 $reason $detail"
printf '%s\n' "package Steam Frame 1629486 $reason $detail"
} > "$REPORT_FILE"
{
@@ -52,6 +74,12 @@ write_unavailable_report() {
printf '%s\n' "SteamKit/PICS package snapshot:"
sed -n '1,40p' "$REPORT_FILE"
} > "$KEY_LINES_FILE"
{
printf '%s\n\n' "# SteamKit / PICS Detail"
printf '%s\n\n' "SteamKit/PICS unavailable: $detail"
printf '%s\n' "The normal watcher continued and wrote placeholder rows so downstream reports still render."
} > "$DETAIL_REPORT_FILE"
}
load_local_env
@@ -96,19 +124,42 @@ if ! command -v dotnet >/dev/null 2>&1; then
exit 0
fi
if ! dotnet run --project "$PROJECT_DIR" -- \
--out-dir "$OUT_DIR" \
--report "$REPORT_FILE" \
--key-lines "$KEY_LINES_FILE" \
>> "$REPORT_DIR/steamkit-pics-dotnet.log" 2>> "$ERROR_FILE"; then
PREVIOUS_REPORT="${STEAMKIT_PREVIOUS_REPORT:-}"
if [ -z "$PREVIOUS_REPORT" ]; then
PREVIOUS_REPORT="$(find_previous_report || true)"
fi
if [ -n "$PREVIOUS_REPORT" ]; then
if ! dotnet run --project "$PROJECT_DIR" -- \
--out-dir "$OUT_DIR" \
--report "$REPORT_FILE" \
--key-lines "$KEY_LINES_FILE" \
--markdown-report "$DETAIL_REPORT_FILE" \
--previous-report "$PREVIOUS_REPORT" \
>> "$REPORT_DIR/steamkit-pics-dotnet.log" 2>> "$ERROR_FILE"; then
detail="SteamKit/PICS helper failed; see steamkit-pics-errors.txt and steamkit-pics-dotnet.log"
if [ ! -s "$REPORT_FILE" ]; then
write_unavailable_report "helper_failed" "$detail"
fi
printf '%s\n' "$detail" >> "$ERROR_FILE"
fi
else
if ! dotnet run --project "$PROJECT_DIR" -- \
--out-dir "$OUT_DIR" \
--report "$REPORT_FILE" \
--key-lines "$KEY_LINES_FILE" \
--markdown-report "$DETAIL_REPORT_FILE" \
>> "$REPORT_DIR/steamkit-pics-dotnet.log" 2>> "$ERROR_FILE"; then
detail="SteamKit/PICS helper failed; see steamkit-pics-errors.txt and steamkit-pics-dotnet.log"
if [ ! -s "$REPORT_FILE" ]; then
write_unavailable_report "helper_failed" "$detail"
if [ ! -s "$REPORT_FILE" ]; then
write_unavailable_report "helper_failed" "$detail"
fi
printf '%s\n' "$detail" >> "$ERROR_FILE"
fi
printf '%s\n' "$detail" >> "$ERROR_FILE"
fi
printf '%s\n' \
"Saved SteamKit/PICS snapshots to $OUT_DIR" \
"Saved matching lines to $KEY_LINES_FILE" \
"Saved SteamKit/PICS report to $REPORT_FILE"
"Saved SteamKit/PICS report to $REPORT_FILE" \
"Saved SteamKit/PICS detail report to $DETAIL_REPORT_FILE"
+4 -2
View File
@@ -7,12 +7,14 @@ if [ "$#" -lt 1 ]; then
fi
RUN_DATE="$1"
BASE_DIR="${2:-$HOME/steam_hardware_watch}"
SCRIPT_DIR="$(CDPATH= cd -- "$(dirname "$0")" && pwd)"
REPO_DIR="$(CDPATH= cd -- "$SCRIPT_DIR/.." && pwd)"
BASE_DIR="${2:-$REPO_DIR/runs}"
RUN_DIR="$BASE_DIR/$RUN_DATE"
mkdir -p "$RUN_DIR/api" "$RUN_DIR/assets" "$RUN_DIR/frames" "$RUN_DIR/reports"
RUN_NOTE_DIR="$(CDPATH= cd -- "$(dirname "$0")/../status/runs" && pwd)"
RUN_NOTE_DIR="$(CDPATH= cd -- "$REPO_DIR/status/runs" && pwd)"
RUN_NOTE="$RUN_NOTE_DIR/$RUN_DATE.md"
if [ ! -f "$RUN_NOTE" ]; then
+2 -2
View File
@@ -7,11 +7,11 @@ if [ "$#" -lt 1 ]; then
fi
RUN_DATE="$1"
BASE_DIR="${2:-$HOME/steam_hardware_watch}"
TRACKING_DIR="${3:-/tmp/SteamTracking-master}"
SCRIPT_DIR="$(CDPATH= cd -- "$(dirname "$0")" && pwd)"
REPO_DIR="$(CDPATH= cd -- "$SCRIPT_DIR/.." && pwd)"
BASE_DIR="${2:-$REPO_DIR/runs}"
TRACKING_DIR="${3:-/tmp/SteamTracking-master}"
KOMODO_ENV_FILE="${KOMODO_ENV_FILE:-$REPO_DIR/.local/komodo-env.sh}"
STEAMDB_ENV_FILE="${STEAMDB_ENV_FILE:-$REPO_DIR/.local/steamdb-env.sh}"
+1
View File
@@ -138,6 +138,7 @@ def build(run_dir: Path):
f"- Blocked assets: `{reports / 'blocked-visual-assets.tsv'}`",
f"- Manual retry URLs: `{reports / 'manual-asset-urls.txt'}`",
f"- SteamKit/PICS packages: `{reports / 'steamkit-pics-packages.tsv'}`",
f"- SteamKit/PICS detail: `{reports / 'steamkit-pics-detail.md'}`",
f"- Customs shipments: `{reports / 'customs-shipments.md'}`",
]
+3 -2
View File
@@ -30,8 +30,9 @@ Last updated: `2026-05-11`
- Controller package `1558609`: `35745078`
- Machine packages `1629446`, `1629447`, `1629458`, `1629460`: `35672615`
- Frame packages `1629484`, `1629486`: `35672606`
- Machine and Frame apps/packages currently return `missing_token` / private product info, but changenumbers are visible and suitable for movement monitoring.
- Raw snapshot: `/Users/sean/steam_hardware_watch/2026-05-11/api/steamkit/pics-product-info.json`
- Machine and Frame apps/packages currently require private PICS metadata tokens, but changenumbers are visible and suitable for movement monitoring.
- Raw snapshot: `/Users/sean/Coding/steam-hardware-watch/runs/2026-05-11/api/steamkit/pics-product-info.json`
- Future runs also write `reports/steamkit-pics-detail.md` with human-readable product grouping, previous changenumber comparison, SHA hash, and exposed app/depot/branch fields.
### SteamDB
+30 -30
View File
@@ -6,35 +6,35 @@
{"date_checked":"2026-04-24","source":"steamdb","entity":"steam-controller","claim":"A hidden Steam Controller unboxing video asset exists and is the strongest late-stage public launch signal in the seeded baseline.","evidence_type":"hidden_media_app","confidence":"high","ref":"https://steamdb.info/app/4653940/","notes":"known internally as steam_controller_unboxing_2026 from prior research"}
{"date_checked":"2026-04-24","source":"steamtracking","entity":"steam-controller","claim":"Valve client assets already contain controller onboarding, firmware, puck, and pairing flows for the new controller ecosystem.","evidence_type":"client_strings","confidence":"medium","ref":"/tmp/SteamTracking-master/Protobufs/webuimessages_steaminput.proto","notes":"Triton, Puck, and pairing/OOBE flows present in seeded local dump"}
{"date_checked":"2026-04-24","source":"analysis","entity":"steam-controller,steam-machine,steam-frame","claim":"Current evidence supports a controller-ahead rollout more than a same-day three-product launch.","evidence_type":"cross_source_inference","confidence":"medium","ref":"/Users/sean.betts/.codex/skills/steam-hardware-watch/status/runs/2026-04-24.md","notes":"driven by controller-only Komodo rollout plus SteamDB unboxing signal"}
{"date_checked": "2026-04-26", "source": "valve-store", "entity": "steam-controller,steam-machine,steam-frame", "claim": "Official Steam Hardware store sale page is published and says the hardware family expands in early 2026.", "evidence_type": "official_store_page", "confidence": "high", "ref": "https://store.steampowered.com/sale/hardware", "notes": "Local artifact: /Users/sean/steam_hardware_watch/2026-04-26/api/valve/steam-hardware-root.html; event modified 2026-04-26T06:06:01Z; includes Controller, Machine, Frame and no exact price."}
{"date_checked": "2026-04-26", "source": "valve-store", "entity": "steam-controller", "claim": "Official Steam Controller sale page is published with a dedicated controller rollout page but no public price or exact date.", "evidence_type": "official_store_page", "confidence": "high", "ref": "https://store.steampowered.com/sale/steamcontroller", "notes": "Local artifact: /Users/sean/steam_hardware_watch/2026-04-26/api/valve/steam-controller-store.html; event modified 2026-04-26T06:05:47Z."}
{"date_checked": "2026-04-26", "source": "valve-store", "entity": "steam-controller,steam-machine,steam-frame", "claim": "Official Steam Hardware store sale page is published and says the hardware family expands in early 2026.", "evidence_type": "official_store_page", "confidence": "high", "ref": "https://store.steampowered.com/sale/hardware", "notes": "Local artifact: /Users/sean/Coding/steam-hardware-watch/runs/2026-04-26/api/valve/steam-hardware-root.html; event modified 2026-04-26T06:06:01Z; includes Controller, Machine, Frame and no exact price."}
{"date_checked": "2026-04-26", "source": "valve-store", "entity": "steam-controller", "claim": "Official Steam Controller sale page is published with a dedicated controller rollout page but no public price or exact date.", "evidence_type": "official_store_page", "confidence": "high", "ref": "https://store.steampowered.com/sale/steamcontroller", "notes": "Local artifact: /Users/sean/Coding/steam-hardware-watch/runs/2026-04-26/api/valve/steam-controller-store.html; event modified 2026-04-26T06:05:47Z."}
{"date_checked": "2026-04-26", "source": "steamdb", "entity": "steam-controller", "claim": "SteamDB currently lists Steam Controller app 4165870 as prerelease with store release date Coming soon.", "evidence_type": "steamdb_app_metadata", "confidence": "medium", "ref": "https://steamdb.info/app/4165870/", "notes": "Browser fetch succeeded; curl helper was blocked. SteamDB shows last record update 2026-04-07T22:07:16Z."}
{"date_checked": "2026-04-26", "source": "steamdb", "entity": "steam-controller", "claim": "SteamDB still shows steam_controller_unboxing_2026 as a released free video app with an available free-on-demand package.", "evidence_type": "hidden_media_app", "confidence": "medium", "ref": "https://steamdb.info/app/4653940/", "notes": "Browser fetch succeeded; app first seen 2026-04-20 and last record update 2026-04-21T22:16:14Z; package 1620489 lists No Price."}
{"date_checked": "2026-04-26", "source": "steamtracking", "entity": "steam-controller", "claim": "Fresh SteamTracking checkout still contains Ibex dongles, Triton pairing, and controller OOBE strings.", "evidence_type": "client_strings", "confidence": "medium", "ref": "/Users/sean/steam_hardware_watch/2026-04-26/reports/steamtracking-pairing-focus.txt", "notes": "Includes ibex_internal, ibex_external, PairDongleTritonConnected, PairDongleTritonDocked, and ShouldTritonPairInOobe in service_steaminputmanager.proto."}
{"date_checked": "2026-04-26", "source": "komodo", "entity": "steam-controller,steam-machine,steam-frame", "claim": "Komodo API access was restored after using a realistic browser user agent; product records remain last modified on 2026-04-24 and no newer Machine or Frame rollout was found.", "evidence_type": "api_recheck", "confidence": "high", "ref": "/Users/sean/steam_hardware_watch/2026-04-26/reports/komodo-product-modified.tsv", "notes": "Root cause of earlier block was helper user-agent Mozilla/5.0 receiving HTTP 403; default curl and realistic Chrome/Safari UAs returned JSON."}
{"date_checked":"2026-04-28","source":"komodo","entity":"steam-controller","claim":"Komodo moved the Steam Controller product record forward again while Machine and Frame remained on their 2026-04-24 modified timestamps.","evidence_type":"product_metadata_delta","confidence":"high","ref":"/Users/sean/steam_hardware_watch/2026-04-28/reports/komodo-product-modified.tsv","notes":"Controller modified 2026-04-28T18:32:11; Machine 2026-04-24T14:32:54; Frame 2026-04-24T14:33:36."}
{"date_checked":"2026-04-28","source":"komodo","entity":"steam-controller","claim":"Komodo added a new Controller specs section and updated the Controller spec-image section with two new AVIF media records.","evidence_type":"sections_media_rollout","confidence":"high","ref":"/Users/sean/steam_hardware_watch/2026-04-28/reports/komodo-controller-sections.tsv","notes":"New section 433617 / 433487 modified 2026-04-27T09:41:01; section 433484 / 433473 modified 2026-04-28T19:05:51 with new media 433664 and 433679."}
{"date_checked":"2026-04-28","source":"komodo","entity":"steam-controller","claim":"The current Komodo visual asset set is fully retrieved and organized into the media-style library.","evidence_type":"asset_retrieval","confidence":"high","ref":"/Users/sean/steam_hardware_watch/2026-04-28/assets/manifests/asset-library.json","notes":"130 discovered and 130 retrieved; library has 11 videos, 11 images, 3 logos, 3 poster frames, 42 thumbnails, and 60 variants, all classified as steam-controller."}
{"date_checked":"2026-04-28","source":"valve-store","entity":"steam-controller,steam-machine,steam-frame","claim":"Official Valve store metadata changed again, including cleaner Steam Hardware submenu URLs under /hardware while still showing only broad 2026 timing.","evidence_type":"official_store_metadata","confidence":"high","ref":"/Users/sean/steam_hardware_watch/2026-04-28/api/valve/steam-hardware-root.html","notes":"Steam Hardware event modified 2026-04-28T10:09:22Z; Controller event modified 2026-04-28T18:31:12Z; no price, preorder date, or exact launch date found."}
{"date_checked":"2026-04-30","source":"komodo","entity":"steam-controller","claim":"Komodo moved the Steam Controller product closer to a sale state by removing the wishlist-only tag and adding the purchasable class while keeping it out of stock.","evidence_type":"product_metadata_delta","confidence":"high","ref":"/Users/sean/steam_hardware_watch/2026-04-30/api/komodo/product-controller-jpy.json","notes":"Controller modified 2026-04-29T12:04:19; class_list removed product_tag-wishlist-only, added purchasable, and retained outofstock; product_tag changed from 112,113 to 112."}
{"date_checked":"2026-04-30","source":"komodo","entity":"steam-machine,steam-frame","claim":"Komodo Machine and Frame products did not receive the Controller sale-state change in this run.","evidence_type":"comparative_absence","confidence":"high","ref":"/Users/sean/steam_hardware_watch/2026-04-30/reports/komodo-product-modified.tsv","notes":"Machine and Frame remain modified 2026-04-24, still carry product_tag-wishlist-only and outofstock, and do not have purchasable."}
{"date_checked":"2026-04-30","source":"komodo","entity":"steam-controller","claim":"Komodo changed the Steam Controller featured media to a newly saved ControllerFront.webp image.","evidence_type":"featured_media_delta","confidence":"high","ref":"/Users/sean/steam_hardware_watch/2026-04-30/api/komodo/media-featured-controller-433684.json","notes":"Featured media changed from 413713 to 433684; media 433684 is ControllerFront.webp, modified 2026-04-28T19:15:27; asset library now includes the original plus generated sizes."}
{"date_checked":"2026-04-30","source":"komodo","entity":"steam-controller","claim":"Komodo updated two Controller sections, but their attached media records did not change.","evidence_type":"section_metadata_delta","confidence":"high","ref":"/Users/sean/steam_hardware_watch/2026-04-30/reports/komodo-controller-sections.tsv","notes":"Section 433356 steam-controller-04-features modified 2026-04-29T11:51:27; section 433484/433473 modified 2026-04-29T10:26:38; associated media timestamps and IDs were unchanged."}
{"date_checked":"2026-04-30","source":"valve-store","entity":"steam-controller,steam-machine,steam-frame","claim":"Official Valve store metadata moved again while still exposing no public price or exact launch date.","evidence_type":"official_store_metadata","confidence":"high","ref":"/Users/sean/steam_hardware_watch/2026-04-30/api/valve/steam-controller-store.html","notes":"Steam Hardware event modified 2026-04-30T05:57:08Z; Steam Controller event modified 2026-04-30T05:57:04Z; controller announcement updated 2026-04-29T20:58:49Z and contains sections including Availability Callout, Purchase Section, Notify me, Komodo, and Tech Specs."}
{"date_checked":"2026-04-30","source":"steamdb","entity":"steam-controller","claim":"SteamDB helper access remained blocked by challenge pages, so no fresh SteamDB metadata was collected in this automated run.","evidence_type":"blocked_fetch","confidence":"high","ref":"/Users/sean/steam_hardware_watch/2026-04-30/reports/steamdb-errors.txt","notes":"Blocked for app 4165870, app 4165870 history, app 4653940, and package 1620489; blocked-page detection prevented challenge HTML from being treated as evidence."}
{"date_checked": "2026-05-01", "source": "valve-store", "entity": "steam-controller", "claim": "Official Valve appdetails now confirm Steam Controller price and package.", "evidence_type": "official_store_api", "confidence": "high", "ref": "/Users/sean/steam_hardware_watch/2026-05-01/api/valve/appdetails-4165870-us.json", "notes": "App 4165870 type hardware; price_overview final_formatted $99.00; package 1558609; package group option text Steam Controller - $99.00."}
{"date_checked": "2026-05-01", "source": "valve-store", "entity": "steam-controller", "claim": "Official Valve store metadata confirms Steam Controller purchase availability on May 4, 2026 at 10AM Pacific.", "evidence_type": "official_store_metadata", "confidence": "high", "ref": "/Users/sean/steam_hardware_watch/2026-05-01/api/valve/steam-controller-store.html", "notes": "Availability Callout says Available for purchase May 4th, 10AM Pacific; purchase section points to reservation package 1558609; controller event modified 2026-05-01T01:16:01Z."}
{"date_checked": "2026-05-01", "source": "valve-store", "entity": "steam-controller", "claim": "Official Valve package details confirm Steam Controller package 1558609 at USD 99.00 with release date May 4, 2026.", "evidence_type": "official_store_api", "confidence": "high", "ref": "/Users/sean/steam_hardware_watch/2026-05-01/api/valve/packagedetails-1558609-us.json", "notes": "Package price final 9900 cents USD; release_date coming_soon false, date May 4, 2026."}
{"date_checked": "2026-05-01", "source": "nbd-customs", "entity": "steam-controller", "claim": "NBD public customs data shows a Valve import row dated 2026-04-04 for WIRELESS PC CONTROLLER from Hong Kong.", "evidence_type": "customs_import_record", "confidence": "medium", "ref": "/Users/sean/steam_hardware_watch/2026-05-01/api/nbd/valve-corporation.html", "notes": "NBD Company Number NBDD3Y527621220; latest trade data 2026-04-04; public row country HONG KONG (CHINA), masked counterparty C***D.; embedded payload reports April 2026 import weight 12970; free view masks detailed shipment fields."}
{"date_checked": "2026-05-01", "source": "importgenius-customs", "entity": "steam-controller,steam-machine,steam-frame", "claim": "ImportGenius lists an April 23, 2026 Ingram Micro C/O Valve Corporation shipment from Tech-Front Chongqing described as GAME CONSOLE.", "evidence_type": "customs_import_record", "confidence": "medium", "ref": "/Users/sean/steam_hardware_watch/2026-05-01/api/importgenius/ingram-micro-c-o-valve-corporation-reader.md", "notes": "Arrival 2026-04-23; BOL SNHBSHACHI264010; importer INGRAM MICRO C/O VALVE CORPORATION; supplier TECH-FRONT (CHONGQING) COMPUTER CO; product GAME CONSOLE .; 42 PKG; 12608 Kgs; container GAOU6922627; package marks include VALVE USA P/NO. references; does not identify which Valve hardware product."}
{"date_checked": "2026-05-01", "source": "nbd-customs", "entity": "steam-controller,steam-machine,steam-frame", "claim": "NBD rendered buyer searches for Valve Corporation and Ingram Micro include a masked April 23, 2026 GAME CONSOLE row.", "evidence_type": "customs_search_result", "confidence": "low", "ref": "/Users/sean/steam_hardware_watch/2026-05-01/api/nbd/search-buyers-valve-corporation-rendered.txt", "notes": "Corroborates the April 23 row at a masked search-result level; NBD buyer search also returns unrelated valve-parts rows, so use this as corroboration only."}
{"date_checked": "2026-05-02", "source": "valve-store", "entity": "steam-controller", "claim": "Official Valve APIs still confirm Steam Controller package 1558609 at USD 99.00 with release date May 4, 2026.", "evidence_type": "official_store_api_recheck", "confidence": "high", "ref": "/Users/sean/steam_hardware_watch/2026-05-02/api/valve/appdetails-4165870-us.json", "notes": "Appdetails price_overview.final_formatted remains $99.00 and package list remains 1558609; packagedetails final price remains 9900 cents USD with release_date date May 4, 2026."}
{"date_checked": "2026-05-02", "source": "valve-store", "entity": "steam-controller,steam-machine,steam-frame", "claim": "Official Valve store metadata moved again, but only Steam Controller has exact purchase timing and a purchase package.", "evidence_type": "official_store_metadata_delta", "confidence": "high", "ref": "/Users/sean/steam_hardware_watch/2026-05-02/api/valve/steam-controller-store.html", "notes": "Controller page still contains Available for purchase May 4th, 10AM Pacific and package 1558609; Controller event modified 2026-05-01T23:18:58Z; Steam Hardware root event modified 2026-05-01T22:43:47Z; no comparable Machine or Frame price/timing found."}
{"date_checked": "2026-05-02", "source": "komodo", "entity": "steam-controller,steam-machine,steam-frame", "claim": "Komodo still separates Controller readiness from Machine and Frame dormancy.", "evidence_type": "product_metadata_recheck", "confidence": "high", "ref": "/Users/sean/steam_hardware_watch/2026-05-02/reports/komodo-product-modified.tsv", "notes": "Controller modified 2026-04-30T19:14:10 and remains purchasable/outofstock without product_tag-wishlist-only; Machine and Frame remain modified 2026-04-24, outofstock, product_tag-wishlist-only, and not purchasable."}
{"date_checked": "2026-05-02", "source": "steamdb", "entity": "steam-controller", "claim": "SteamDB helper access remained blocked by challenge pages in the automated May 2 run.", "evidence_type": "blocked_fetch", "confidence": "high", "ref": "/Users/sean/steam_hardware_watch/2026-05-02/reports/steamdb-errors.txt", "notes": "Blocked for app 4165870, app 4165870 history, app 4653940, and package 1620489; no fresh SteamDB metadata was collected."}
{"date_checked": "2026-05-04", "source": "valve-store", "entity": "steam-controller,steam-machine,steam-frame", "claim": "Official Valve metadata moved on launch day while only Steam Controller still has a confirmed purchase package, price, and release date.", "evidence_type": "official_store_metadata_delta", "confidence": "high", "ref": "/Users/sean/steam_hardware_watch/2026-05-04/api/valve/steam-controller-store.html", "notes": "Steam Controller event modified 2026-05-04T18:27:52Z; Steam Hardware root modified 2026-05-04T18:27:56Z; appdetails and packagedetails still confirm package 1558609, USD $99.00, release date May 4, 2026; Machine and Frame still lack comparable price or exact timing."}
{"date_checked": "2026-05-04", "source": "steamtracking", "entity": "steam-controller", "claim": "Fresh SteamTracking checkout shows the Triton/Ibex pairing API surface in the Steam Android APK string dump as well as existing proto and web UI surfaces.", "evidence_type": "client_strings", "confidence": "medium", "ref": "/Users/sean/steam_hardware_watch/2026-05-04/reports/steamtracking-pairing-focus.txt", "notes": "Random/SteamApkStrings.txt now includes CSteamInputService_PairDongleTritonConnected, PairDongleTritonDocked, ShouldTritonPairInOobe, UnpairedTritonDocked, UnpairedTritonPluggedIn, ibex_internal, and ibex_external. This broadens client-surface evidence but does not change price or release-date confidence."}
{"date_checked": "2026-05-04", "source": "steamos-mirror", "entity": "steam-machine,steam-frame", "claim": "First default SteamOS package mirror pass did not expose direct Machine or Frame codename/package evidence.", "evidence_type": "package_mirror_baseline", "confidence": "medium", "ref": "/Users/sean/steam_hardware_watch/2026-05-04/reports/steamos-mirror-packages.tsv", "notes": "Default holo-3.8, holo-main, jupiter-3.8, and jupiter-main pass produced 758 package rows with no errors. No Fremont, Deckard, Roy, Steam Frame, Steam Machine, ARM/Snapdragon, or new product-specific top-level repo namespace appeared; notable hits were Deck/Jupiter-adjacent foxnet, linux-firmware-neptune, and plasma-remotecontrollers."}
{"date_checked": "2026-05-10", "source": "valve-store", "entity": "steam-controller,steam-machine,steam-frame", "claim": "Valve Store APIs confirm Steam Controller remains public with package 1558609 and USD 99.00 while Steam Machine and Steam Frame apps remain coming soon with no public packages or price.", "evidence_type": "official_store_api_recheck", "confidence": "high", "ref": "/Users/sean/steam_hardware_watch/2026-05-10/reports/valve-reservation-packages.tsv", "notes": "appdetails: Controller public with packages=1558609 and package_groups=1; Frame 4165890 and Machine 4165910 public app metadata but package_groups=0, no packages, no price; Machine packages 1629446/1629447/1629458/1629460 and Frame packages 1629484/1629486 still packagedetails success:false."}
{"date_checked": "2026-05-10", "source": "steamdb", "entity": "steam-controller,steam-machine,steam-frame", "claim": "SteamDB reservation package monitor is now part of the baseline, but automated and browser-fallback fetches were blocked for all watched package pages.", "evidence_type": "blocked_fetch", "confidence": "high", "ref": "/Users/sean/steam_hardware_watch/2026-05-10/reports/steamdb-reservation-packages.tsv", "notes": "Watched package IDs: 1558609, 1629446, 1629447, 1629458, 1629460, 1629484, 1629486. All rows are missing_or_blocked after SteamDB challenge pages, so a manual trusted browser pass is still needed for Last Record Update/changenumber baseline."}
{"date_checked": "2026-05-11", "source": "steamkit-pics", "entity": "steam-controller,steam-machine,steam-frame", "claim": "SteamKit/PICS now provides a direct baseline changenumber snapshot for watched Valve hardware apps and reservation packages.", "evidence_type": "steam_product_info_baseline", "confidence": "high", "ref": "/Users/sean/steam_hardware_watch/2026-05-11/reports/steamkit-pics-packages.tsv", "notes": "Controller app 4165870 changenumber 35731145; Frame app 4165890 and Machine app 4165910 changenumber 35675573; Controller package 1558609 changenumber 35745078; Machine packages 1629446/1629447/1629458/1629460 changenumber 35672615; Frame packages 1629484/1629486 changenumber 35672606. Machine and Frame rows remain private/missing_token but visible changenumbers are enough for movement monitoring."}
{"date_checked": "2026-04-26", "source": "steamtracking", "entity": "steam-controller", "claim": "Fresh SteamTracking checkout still contains Ibex dongles, Triton pairing, and controller OOBE strings.", "evidence_type": "client_strings", "confidence": "medium", "ref": "/Users/sean/Coding/steam-hardware-watch/runs/2026-04-26/reports/steamtracking-pairing-focus.txt", "notes": "Includes ibex_internal, ibex_external, PairDongleTritonConnected, PairDongleTritonDocked, and ShouldTritonPairInOobe in service_steaminputmanager.proto."}
{"date_checked": "2026-04-26", "source": "komodo", "entity": "steam-controller,steam-machine,steam-frame", "claim": "Komodo API access was restored after using a realistic browser user agent; product records remain last modified on 2026-04-24 and no newer Machine or Frame rollout was found.", "evidence_type": "api_recheck", "confidence": "high", "ref": "/Users/sean/Coding/steam-hardware-watch/runs/2026-04-26/reports/komodo-product-modified.tsv", "notes": "Root cause of earlier block was helper user-agent Mozilla/5.0 receiving HTTP 403; default curl and realistic Chrome/Safari UAs returned JSON."}
{"date_checked":"2026-04-28","source":"komodo","entity":"steam-controller","claim":"Komodo moved the Steam Controller product record forward again while Machine and Frame remained on their 2026-04-24 modified timestamps.","evidence_type":"product_metadata_delta","confidence":"high","ref":"/Users/sean/Coding/steam-hardware-watch/runs/2026-04-28/reports/komodo-product-modified.tsv","notes":"Controller modified 2026-04-28T18:32:11; Machine 2026-04-24T14:32:54; Frame 2026-04-24T14:33:36."}
{"date_checked":"2026-04-28","source":"komodo","entity":"steam-controller","claim":"Komodo added a new Controller specs section and updated the Controller spec-image section with two new AVIF media records.","evidence_type":"sections_media_rollout","confidence":"high","ref":"/Users/sean/Coding/steam-hardware-watch/runs/2026-04-28/reports/komodo-controller-sections.tsv","notes":"New section 433617 / 433487 modified 2026-04-27T09:41:01; section 433484 / 433473 modified 2026-04-28T19:05:51 with new media 433664 and 433679."}
{"date_checked":"2026-04-28","source":"komodo","entity":"steam-controller","claim":"The current Komodo visual asset set is fully retrieved and organized into the media-style library.","evidence_type":"asset_retrieval","confidence":"high","ref":"/Users/sean/Coding/steam-hardware-watch/runs/2026-04-28/assets/manifests/asset-library.json","notes":"130 discovered and 130 retrieved; library has 11 videos, 11 images, 3 logos, 3 poster frames, 42 thumbnails, and 60 variants, all classified as steam-controller."}
{"date_checked":"2026-04-28","source":"valve-store","entity":"steam-controller,steam-machine,steam-frame","claim":"Official Valve store metadata changed again, including cleaner Steam Hardware submenu URLs under /hardware while still showing only broad 2026 timing.","evidence_type":"official_store_metadata","confidence":"high","ref":"/Users/sean/Coding/steam-hardware-watch/runs/2026-04-28/api/valve/steam-hardware-root.html","notes":"Steam Hardware event modified 2026-04-28T10:09:22Z; Controller event modified 2026-04-28T18:31:12Z; no price, preorder date, or exact launch date found."}
{"date_checked":"2026-04-30","source":"komodo","entity":"steam-controller","claim":"Komodo moved the Steam Controller product closer to a sale state by removing the wishlist-only tag and adding the purchasable class while keeping it out of stock.","evidence_type":"product_metadata_delta","confidence":"high","ref":"/Users/sean/Coding/steam-hardware-watch/runs/2026-04-30/api/komodo/product-controller-jpy.json","notes":"Controller modified 2026-04-29T12:04:19; class_list removed product_tag-wishlist-only, added purchasable, and retained outofstock; product_tag changed from 112,113 to 112."}
{"date_checked":"2026-04-30","source":"komodo","entity":"steam-machine,steam-frame","claim":"Komodo Machine and Frame products did not receive the Controller sale-state change in this run.","evidence_type":"comparative_absence","confidence":"high","ref":"/Users/sean/Coding/steam-hardware-watch/runs/2026-04-30/reports/komodo-product-modified.tsv","notes":"Machine and Frame remain modified 2026-04-24, still carry product_tag-wishlist-only and outofstock, and do not have purchasable."}
{"date_checked":"2026-04-30","source":"komodo","entity":"steam-controller","claim":"Komodo changed the Steam Controller featured media to a newly saved ControllerFront.webp image.","evidence_type":"featured_media_delta","confidence":"high","ref":"/Users/sean/Coding/steam-hardware-watch/runs/2026-04-30/api/komodo/media-featured-controller-433684.json","notes":"Featured media changed from 413713 to 433684; media 433684 is ControllerFront.webp, modified 2026-04-28T19:15:27; asset library now includes the original plus generated sizes."}
{"date_checked":"2026-04-30","source":"komodo","entity":"steam-controller","claim":"Komodo updated two Controller sections, but their attached media records did not change.","evidence_type":"section_metadata_delta","confidence":"high","ref":"/Users/sean/Coding/steam-hardware-watch/runs/2026-04-30/reports/komodo-controller-sections.tsv","notes":"Section 433356 steam-controller-04-features modified 2026-04-29T11:51:27; section 433484/433473 modified 2026-04-29T10:26:38; associated media timestamps and IDs were unchanged."}
{"date_checked":"2026-04-30","source":"valve-store","entity":"steam-controller,steam-machine,steam-frame","claim":"Official Valve store metadata moved again while still exposing no public price or exact launch date.","evidence_type":"official_store_metadata","confidence":"high","ref":"/Users/sean/Coding/steam-hardware-watch/runs/2026-04-30/api/valve/steam-controller-store.html","notes":"Steam Hardware event modified 2026-04-30T05:57:08Z; Steam Controller event modified 2026-04-30T05:57:04Z; controller announcement updated 2026-04-29T20:58:49Z and contains sections including Availability Callout, Purchase Section, Notify me, Komodo, and Tech Specs."}
{"date_checked":"2026-04-30","source":"steamdb","entity":"steam-controller","claim":"SteamDB helper access remained blocked by challenge pages, so no fresh SteamDB metadata was collected in this automated run.","evidence_type":"blocked_fetch","confidence":"high","ref":"/Users/sean/Coding/steam-hardware-watch/runs/2026-04-30/reports/steamdb-errors.txt","notes":"Blocked for app 4165870, app 4165870 history, app 4653940, and package 1620489; blocked-page detection prevented challenge HTML from being treated as evidence."}
{"date_checked": "2026-05-01", "source": "valve-store", "entity": "steam-controller", "claim": "Official Valve appdetails now confirm Steam Controller price and package.", "evidence_type": "official_store_api", "confidence": "high", "ref": "/Users/sean/Coding/steam-hardware-watch/runs/2026-05-01/api/valve/appdetails-4165870-us.json", "notes": "App 4165870 type hardware; price_overview final_formatted $99.00; package 1558609; package group option text Steam Controller - $99.00."}
{"date_checked": "2026-05-01", "source": "valve-store", "entity": "steam-controller", "claim": "Official Valve store metadata confirms Steam Controller purchase availability on May 4, 2026 at 10AM Pacific.", "evidence_type": "official_store_metadata", "confidence": "high", "ref": "/Users/sean/Coding/steam-hardware-watch/runs/2026-05-01/api/valve/steam-controller-store.html", "notes": "Availability Callout says Available for purchase May 4th, 10AM Pacific; purchase section points to reservation package 1558609; controller event modified 2026-05-01T01:16:01Z."}
{"date_checked": "2026-05-01", "source": "valve-store", "entity": "steam-controller", "claim": "Official Valve package details confirm Steam Controller package 1558609 at USD 99.00 with release date May 4, 2026.", "evidence_type": "official_store_api", "confidence": "high", "ref": "/Users/sean/Coding/steam-hardware-watch/runs/2026-05-01/api/valve/packagedetails-1558609-us.json", "notes": "Package price final 9900 cents USD; release_date coming_soon false, date May 4, 2026."}
{"date_checked": "2026-05-01", "source": "nbd-customs", "entity": "steam-controller", "claim": "NBD public customs data shows a Valve import row dated 2026-04-04 for WIRELESS PC CONTROLLER from Hong Kong.", "evidence_type": "customs_import_record", "confidence": "medium", "ref": "/Users/sean/Coding/steam-hardware-watch/runs/2026-05-01/api/nbd/valve-corporation.html", "notes": "NBD Company Number NBDD3Y527621220; latest trade data 2026-04-04; public row country HONG KONG (CHINA), masked counterparty C***D.; embedded payload reports April 2026 import weight 12970; free view masks detailed shipment fields."}
{"date_checked": "2026-05-01", "source": "importgenius-customs", "entity": "steam-controller,steam-machine,steam-frame", "claim": "ImportGenius lists an April 23, 2026 Ingram Micro C/O Valve Corporation shipment from Tech-Front Chongqing described as GAME CONSOLE.", "evidence_type": "customs_import_record", "confidence": "medium", "ref": "/Users/sean/Coding/steam-hardware-watch/runs/2026-05-01/api/importgenius/ingram-micro-c-o-valve-corporation-reader.md", "notes": "Arrival 2026-04-23; BOL SNHBSHACHI264010; importer INGRAM MICRO C/O VALVE CORPORATION; supplier TECH-FRONT (CHONGQING) COMPUTER CO; product GAME CONSOLE .; 42 PKG; 12608 Kgs; container GAOU6922627; package marks include VALVE USA P/NO. references; does not identify which Valve hardware product."}
{"date_checked": "2026-05-01", "source": "nbd-customs", "entity": "steam-controller,steam-machine,steam-frame", "claim": "NBD rendered buyer searches for Valve Corporation and Ingram Micro include a masked April 23, 2026 GAME CONSOLE row.", "evidence_type": "customs_search_result", "confidence": "low", "ref": "/Users/sean/Coding/steam-hardware-watch/runs/2026-05-01/api/nbd/search-buyers-valve-corporation-rendered.txt", "notes": "Corroborates the April 23 row at a masked search-result level; NBD buyer search also returns unrelated valve-parts rows, so use this as corroboration only."}
{"date_checked": "2026-05-02", "source": "valve-store", "entity": "steam-controller", "claim": "Official Valve APIs still confirm Steam Controller package 1558609 at USD 99.00 with release date May 4, 2026.", "evidence_type": "official_store_api_recheck", "confidence": "high", "ref": "/Users/sean/Coding/steam-hardware-watch/runs/2026-05-02/api/valve/appdetails-4165870-us.json", "notes": "Appdetails price_overview.final_formatted remains $99.00 and package list remains 1558609; packagedetails final price remains 9900 cents USD with release_date date May 4, 2026."}
{"date_checked": "2026-05-02", "source": "valve-store", "entity": "steam-controller,steam-machine,steam-frame", "claim": "Official Valve store metadata moved again, but only Steam Controller has exact purchase timing and a purchase package.", "evidence_type": "official_store_metadata_delta", "confidence": "high", "ref": "/Users/sean/Coding/steam-hardware-watch/runs/2026-05-02/api/valve/steam-controller-store.html", "notes": "Controller page still contains Available for purchase May 4th, 10AM Pacific and package 1558609; Controller event modified 2026-05-01T23:18:58Z; Steam Hardware root event modified 2026-05-01T22:43:47Z; no comparable Machine or Frame price/timing found."}
{"date_checked": "2026-05-02", "source": "komodo", "entity": "steam-controller,steam-machine,steam-frame", "claim": "Komodo still separates Controller readiness from Machine and Frame dormancy.", "evidence_type": "product_metadata_recheck", "confidence": "high", "ref": "/Users/sean/Coding/steam-hardware-watch/runs/2026-05-02/reports/komodo-product-modified.tsv", "notes": "Controller modified 2026-04-30T19:14:10 and remains purchasable/outofstock without product_tag-wishlist-only; Machine and Frame remain modified 2026-04-24, outofstock, product_tag-wishlist-only, and not purchasable."}
{"date_checked": "2026-05-02", "source": "steamdb", "entity": "steam-controller", "claim": "SteamDB helper access remained blocked by challenge pages in the automated May 2 run.", "evidence_type": "blocked_fetch", "confidence": "high", "ref": "/Users/sean/Coding/steam-hardware-watch/runs/2026-05-02/reports/steamdb-errors.txt", "notes": "Blocked for app 4165870, app 4165870 history, app 4653940, and package 1620489; no fresh SteamDB metadata was collected."}
{"date_checked": "2026-05-04", "source": "valve-store", "entity": "steam-controller,steam-machine,steam-frame", "claim": "Official Valve metadata moved on launch day while only Steam Controller still has a confirmed purchase package, price, and release date.", "evidence_type": "official_store_metadata_delta", "confidence": "high", "ref": "/Users/sean/Coding/steam-hardware-watch/runs/2026-05-04/api/valve/steam-controller-store.html", "notes": "Steam Controller event modified 2026-05-04T18:27:52Z; Steam Hardware root modified 2026-05-04T18:27:56Z; appdetails and packagedetails still confirm package 1558609, USD $99.00, release date May 4, 2026; Machine and Frame still lack comparable price or exact timing."}
{"date_checked": "2026-05-04", "source": "steamtracking", "entity": "steam-controller", "claim": "Fresh SteamTracking checkout shows the Triton/Ibex pairing API surface in the Steam Android APK string dump as well as existing proto and web UI surfaces.", "evidence_type": "client_strings", "confidence": "medium", "ref": "/Users/sean/Coding/steam-hardware-watch/runs/2026-05-04/reports/steamtracking-pairing-focus.txt", "notes": "Random/SteamApkStrings.txt now includes CSteamInputService_PairDongleTritonConnected, PairDongleTritonDocked, ShouldTritonPairInOobe, UnpairedTritonDocked, UnpairedTritonPluggedIn, ibex_internal, and ibex_external. This broadens client-surface evidence but does not change price or release-date confidence."}
{"date_checked": "2026-05-04", "source": "steamos-mirror", "entity": "steam-machine,steam-frame", "claim": "First default SteamOS package mirror pass did not expose direct Machine or Frame codename/package evidence.", "evidence_type": "package_mirror_baseline", "confidence": "medium", "ref": "/Users/sean/Coding/steam-hardware-watch/runs/2026-05-04/reports/steamos-mirror-packages.tsv", "notes": "Default holo-3.8, holo-main, jupiter-3.8, and jupiter-main pass produced 758 package rows with no errors. No Fremont, Deckard, Roy, Steam Frame, Steam Machine, ARM/Snapdragon, or new product-specific top-level repo namespace appeared; notable hits were Deck/Jupiter-adjacent foxnet, linux-firmware-neptune, and plasma-remotecontrollers."}
{"date_checked": "2026-05-10", "source": "valve-store", "entity": "steam-controller,steam-machine,steam-frame", "claim": "Valve Store APIs confirm Steam Controller remains public with package 1558609 and USD 99.00 while Steam Machine and Steam Frame apps remain coming soon with no public packages or price.", "evidence_type": "official_store_api_recheck", "confidence": "high", "ref": "/Users/sean/Coding/steam-hardware-watch/runs/2026-05-10/reports/valve-reservation-packages.tsv", "notes": "appdetails: Controller public with packages=1558609 and package_groups=1; Frame 4165890 and Machine 4165910 public app metadata but package_groups=0, no packages, no price; Machine packages 1629446/1629447/1629458/1629460 and Frame packages 1629484/1629486 still packagedetails success:false."}
{"date_checked": "2026-05-10", "source": "steamdb", "entity": "steam-controller,steam-machine,steam-frame", "claim": "SteamDB reservation package monitor is now part of the baseline, but automated and browser-fallback fetches were blocked for all watched package pages.", "evidence_type": "blocked_fetch", "confidence": "high", "ref": "/Users/sean/Coding/steam-hardware-watch/runs/2026-05-10/reports/steamdb-reservation-packages.tsv", "notes": "Watched package IDs: 1558609, 1629446, 1629447, 1629458, 1629460, 1629484, 1629486. All rows are missing_or_blocked after SteamDB challenge pages, so a manual trusted browser pass is still needed for Last Record Update/changenumber baseline."}
{"date_checked": "2026-05-11", "source": "steamkit-pics", "entity": "steam-controller,steam-machine,steam-frame", "claim": "SteamKit/PICS now provides a direct baseline changenumber snapshot for watched Valve hardware apps and reservation packages.", "evidence_type": "steam_product_info_baseline", "confidence": "high", "ref": "/Users/sean/Coding/steam-hardware-watch/runs/2026-05-11/reports/steamkit-pics-packages.tsv", "notes": "Controller app 4165870 changenumber 35731145; Frame app 4165890 and Machine app 4165910 changenumber 35675573; Controller package 1558609 changenumber 35745078; Machine packages 1629446/1629447/1629458/1629460 changenumber 35672615; Frame packages 1629484/1629486 changenumber 35672606. Machine and Frame rows require private PICS metadata tokens but visible changenumbers are enough for movement monitoring."}
+66
View File
@@ -0,0 +1,66 @@
# Run Note: 2026-04-26
## Summary
- Artifacts: `/Users/sean/Coding/steam-hardware-watch/runs/2026-04-26`
- Official Valve store pages are now the strongest current signal: `/sale/hardware` groups Steam Controller, Steam Machine, and Steam Frame and says the hardware family expands in early 2026.
- No confirmed price, exact release date, preorder date, or same-day availability date was found.
- Controller remains furthest along because it has a dedicated official page, SteamDB prerelease app state, the unboxing video package, and active client onboarding and pairing strings.
## Source Checks
### Komodo
- Initial automated Komodo fetch was blocked because the helper used the generic user agent `Mozilla/5.0`, which returned HTTP 403.
- After patching the helper to use a realistic Chrome user agent, Komodo API access succeeded:
- `/Users/sean/Coding/steam-hardware-watch/runs/2026-04-26/api/komodo`
- `/Users/sean/Coding/steam-hardware-watch/runs/2026-04-26/reports/komodo-product-modified.tsv`
- `/Users/sean/Coding/steam-hardware-watch/runs/2026-04-26/reports/komodo-visual-assets.tsv`
- Product modified timestamps remain:
- Controller: `2026-04-24T15:12:12`
- Machine: `2026-04-24T14:32:54`
- Frame: `2026-04-24T14:33:36`
- Current asset ledger found `108` visual asset URLs and retrieved all `108`, including AVIF, MP4, and WEBM assets.
### SteamDB
- The repo curl helper was blocked by SteamDB.
- Browser verification succeeded:
- `https://steamdb.info/app/4165870/` shows Steam Controller app `4165870`, `ReleaseState prerelease`, and store release date `Coming soon`.
- `https://steamdb.info/app/4653940/` shows `steam_controller_unboxing_2026`, app `4653940`, as a released free video app first seen on `2026-04-20`.
- `https://steamdb.info/sub/1620489/` shows package `1620489` available as free on demand with app `4653940` listed as `No Price`.
### SteamTracking / GameTracking
- Fresh shallow checkout: `/tmp/SteamTracking-master`
- Pairing-focused output:
- `/Users/sean/Coding/steam-hardware-watch/runs/2026-04-26/reports/steamtracking-pairing-focus.txt`
- Material hits include `ibex_internal`, `ibex_external`, `PairDongleTritonConnected`, `PairDongleTritonDocked`, and `ShouldTritonPairInOobe`.
### Valve Support / CDN
- Saved official Valve pages:
- `/Users/sean/Coding/steam-hardware-watch/runs/2026-04-26/api/valve/steam-hardware-root.html`
- `/Users/sean/Coding/steam-hardware-watch/runs/2026-04-26/api/valve/steam-controller-store.html`
- `/Users/sean/Coding/steam-hardware-watch/runs/2026-04-26/api/valve/steam-support-deck.html`
- `/Users/sean/Coding/steam-hardware-watch/runs/2026-04-26/api/valve/steamdeck-site.html`
- Extracted event metadata:
- Steam Hardware page modified `2026-04-26T06:06:01Z`, sale vanity `hardware`, six sections.
- Steam Controller page modified `2026-04-26T06:05:47Z`, sale vanity `steamcontroller`, twenty sections.
- The store pages expose broad timing only: early 2026 / coming in 2026.
### Customs / Regulatory
- Quick web check found no new relevant Valve regulatory filing for the 2026 devices. Search results were old Valve controller/deck records or unrelated "Steam Machine" products.
## Effect On Key Questions
- Price: unchanged, no confirmed public price.
- Release date: improved from no official date window to official broad `early 2026` / `coming in 2026`; exact date still unknown.
- Same-time launch: improved for shared public rollout window, still unconfirmed for same-day sale, preorder, or shipment.
## Next Checks
- Retry Komodo with the optional dedicated browser bootstrap if protected Komodo media matters.
- Recheck SteamDB through browser-capable tooling, because plain curl is blocked.
- Watch Valve store page event metadata for price fields, preorder CTAs, or modified release wording.
+66
View File
@@ -0,0 +1,66 @@
# Run Note: 2026-04-28
## Summary
- Reran the full Steam Hardware watch against an updated SteamTracking checkout.
- Komodo API access worked, Valve store pages were reachable, and SteamDB curl-style access was still blocked.
- The material changes are controller-heavy: Controller product metadata moved again, a new specs section appeared, and the spec-image section gained new AVIF media.
## Source Checks
### Komodo
- Product modified timestamps:
- Controller: `2026-04-28T18:32:11`
- Machine: `2026-04-24T14:32:54`
- Frame: `2026-04-24T14:33:36`
- Added section: `433617` / `433487`, `Steam Controller - 10 Specs`, modified `2026-04-27T09:41:01`.
- Updated section: `433484` / `433473`, `Steam controller - 09 Spec image`, modified `2026-04-28T19:05:51`.
- New media records in the updated spec-image section:
- `433664`, `21943cb2557144ba65ee5c509e9110a0.avif`
- `433679`, `9e7ba952102780b10b80106356eaa460.avif`
- Asset pull found `130` visual assets and retrieved all `130`. Library counts: `11` videos, `11` images, `3` logos, `3` poster frames, `42` thumbnails, `60` variants.
### SteamDB
- Helper fetches were still blocked for:
- `https://steamdb.info/app/4165870/`
- `https://steamdb.info/app/4165870/history/`
- `https://steamdb.info/app/4653940/`
- `https://steamdb.info/sub/1620489/`
- No fresh browser verification was done in this run.
### SteamTracking / GameTracking
- Updated `/tmp/SteamTracking-master` from `d0def65` to `0358379`.
- Pairing-focused controller strings are still present, including `ibex_internal`, `ibex_external`, `PairDongleTritonConnected`, and `PairDongleTritonDocked`.
### Valve Support / CDN
- Valve store pages were reachable.
- Steam Hardware root page still advertises the family expanding in early 2026.
- Embedded event metadata changed:
- Steam Hardware event modified: `2026-04-28T10:09:22Z`
- Steam Controller event modified: `2026-04-28T18:31:12Z`
- Embedded submenu URLs now use cleaner paths:
- `/hardware`
- `/hardware/steamcontroller`
- `/hardware/steammachine`
- `/hardware/steamframe`
- No price, preorder date, ship date, or exact launch date found.
### Customs / Regulatory
- Not rerun in this automated pass.
## Effect On Key Questions
- Price: still no confirmed public price.
- Release date: still broad `early 2026` / `coming in 2026`, no exact date.
- Same-time launch: official Valve grouping still supports a shared public rollout window, but the fresh Komodo movement remains controller-only, so exact same-day availability is still unconfirmed.
## Next Checks
- Recheck Komodo Machine and Frame sections/media for comparable fresh rollouts.
- Recheck SteamDB via browser session for app `4165870`, app `4653940`, and package `1620489`.
- Watch Valve store metadata and `/hardware/...` paths for price, preorder, or availability fields.
+73
View File
@@ -0,0 +1,73 @@
# Run Note: 2026-04-30
## Summary
- Reran the full Steam Hardware watch against an updated SteamTracking checkout.
- Komodo API access worked, Valve store pages were reachable, and SteamDB helper access was blocked by challenge pages.
- The material changes are still controller-heavy: Komodo moved the Controller product closer to sale state, changed its featured media, and Valve updated official controller store metadata.
## Source Checks
### Komodo
- Product modified timestamps:
- Controller: `2026-04-29T12:04:19`
- Machine: `2026-04-24T14:32:54`
- Frame: `2026-04-24T14:33:36`
- Controller class/tag delta:
- Removed `product_tag-wishlist-only`.
- Added `purchasable`.
- Kept `outofstock`.
- `product_tag` changed from `[112, 113]` to `[112]`; tag `113` is `wishlist-only`.
- Machine and Frame still have `product_tag-wishlist-only`, remain `outofstock`, and do not have `purchasable`.
- Controller featured media changed from `413713` to `433684`.
- Saved featured media `433684`, `ControllerFront.webp`, modified `2026-04-28T19:15:27`.
- Updated sections:
- `433356`, `steam-controller-04-features`, modified `2026-04-29T11:51:27`.
- `433484`, `433473`, modified `2026-04-29T10:26:38`.
- Attached media for the changed sections did not change.
- Asset pull found `141` visual assets and retrieved all `141`. Library counts: `11` videos, `12` images, `3` logos, `3` poster frames, `45` thumbnails, `67` variants.
### SteamDB
- Helper fetches were blocked for:
- `https://steamdb.info/app/4165870/`
- `https://steamdb.info/app/4165870/history/`
- `https://steamdb.info/app/4653940/`
- `https://steamdb.info/sub/1620489/`
- Blocked-page detection worked: challenge pages were not treated as evidence.
- No fresh browser verification was done in this run.
### SteamTracking / GameTracking
- Updated `/tmp/SteamTracking-master` from `0358379` to `79adf88`.
- Pairing-focused controller strings are still present, including `ibex_internal`, `ibex_external`, `PairDongleTritonConnected`, and `PairDongleTritonDocked`.
- No clean semantic SteamTracking delta was identified beyond path/chunk churn in the updated checkout.
### Valve Support / CDN
- Valve store pages were reachable.
- Steam Hardware root event metadata:
- Event modified: `2026-04-30T05:57:08Z`
- Announcement updated: `2026-04-27T17:51:20Z`
- Steam Controller event metadata:
- Event modified: `2026-04-30T05:57:04Z`
- Announcement updated: `2026-04-29T20:58:49Z`
- Controller sale metadata now has `23` sections, including `Availability Callout`, `Purchase Section`, `Notify me`, `Komodo`, and `Tech Specs`.
- No price, preorder date, ship date, or exact launch date found.
### Customs / Regulatory
- Not rerun in this automated pass.
## Effect On Key Questions
- Price: still no confirmed public price.
- Release date: still broad `early 2026` / `coming in 2026`, no exact date.
- Same-time launch: official Valve grouping still supports a shared public rollout window, but fresh commerce-state movement remains controller-only. Exact same-day availability is still unconfirmed.
## Next Checks
- Recheck Komodo Machine and Frame product classes/tags for matching removal of `wishlist-only`.
- Recheck SteamDB via browser session for app `4165870`, app `4653940`, and package `1620489`.
- Watch Valve store metadata and `/hardware/...` paths for price, preorder, or availability fields.
+68
View File
@@ -0,0 +1,68 @@
# Run Note: 2026-05-01
## Summary
- Checked the NBD public Valve Corporation customs page suggested by the user.
- Saved the public NBD artifact and extracted the relevant `WIRELESS PC CONTROLLER` import row.
- While validating the current state, re-fetched official Valve endpoints and found the Steam Controller price and purchase date are now public.
## Source Checks
### Komodo
- Not rerun in this targeted pass.
### SteamDB
- Not rerun in this targeted pass.
- Official Valve appdetails now supersede the last SteamDB state for Steam Controller price/date.
### SteamTracking / GameTracking
- Not rerun in this targeted pass.
### Valve Support / CDN
- Saved fresh Valve Controller and Hardware store artifacts.
- Steam Controller store event modified: `2026-05-01T01:16:01Z`.
- Steam Hardware root event modified: `2026-05-01T01:16:08Z`.
- Steam Controller availability callout now says `Available for purchase May 4th, 10AM Pacific`.
- Purchase section points to reservation package `1558609`.
- Official appdetails for app `4165870` show USD price `$99.00`, package `1558609`, and release date `May 4, 2026`.
- Official packagedetails for package `1558609` show USD final price `9900` cents and release date `May 4, 2026`.
- No comparable Machine or Frame price/date found in this targeted pass.
### Customs / Regulatory
- Saved NBD public Valve Corporation page:
- `/Users/sean/Coding/steam-hardware-watch/runs/2026-05-01/api/nbd/valve-corporation.html`
- Extracted report:
- `/Users/sean/Coding/steam-hardware-watch/runs/2026-05-01/reports/nbd-valve-corporation.md`
- NBD public row shows `2026-04-04` import, product description `WIRELESS PC CONTROLLER`, country `HONG KONG (CHINA)`, masked counterparty `C***D.`
- Embedded NBD payload reports April 2026 import weight `12970` for the company data series.
- The free NBD page masks details such as package count, bill of lading number, consignee address, and full counterparty name.
- Follow-up on the user's April 23 `GAME CONSOLE` note found a stronger ImportGenius record for `INGRAM MICRO C/O VALVE CORPORATION`:
- Report: `/Users/sean/Coding/steam-hardware-watch/runs/2026-05-01/reports/customs-game-console-apr23.md`
- Reader artifact: `/Users/sean/Coding/steam-hardware-watch/runs/2026-05-01/api/importgenius/ingram-micro-c-o-valve-corporation-reader.md`
- Bill of lading: `SNHBSHACHI264010`
- Arrival date: `2026-04-23`
- Product: `GAME CONSOLE .`
- Supplier: `TECH-FRONT (CHONGQING) COMPUTER CO`
- Weight and quantity: `12608 Kgs`, `42 PKG`
- Sample details include Valve-marked package references: `VALVE USA P/NO. 1AC1124-21AC1124 P/NO. 1AC1 125-9AC1125 P/NO. 1AC1123-12AC1123`.
- NBD rendered buyer searches for `Valve Corporation` and `Ingram Micro` also show masked April 23 `GAME CONSOLE .` rows.
- Assessment: this is meaningful launch-logistics corroboration for Valve hardware movement, but it does not identify whether the shipment is Controller, Machine, Frame, or another Valve hardware item.
## Effect On Key Questions
- Price: Steam Controller price is now confirmed at `$99.00` in official US Valve appdetails. Machine and Frame still unpriced.
- Release date: Steam Controller purchase date is now confirmed as `May 4, 2026` at `10AM Pacific`. Machine and Frame remain broad `2026`.
- Same-time launch: controller-first rollout is now the best answer. The full trio is not launching together unless Machine and Frame receive last-minute matching purchase pages.
- Customs/regulatory: the April 23 `GAME CONSOLE .` shipment strengthens evidence that Valve hardware logistics are active close to launch, but does not alter price/date confidence because it is not a primary Valve publication.
## Next Checks
- Recheck Komodo for Machine and Frame movement.
- Recheck SteamDB with browser fallback now that official appdetails moved.
- Add NBD to the slower customs/regulatory source rotation.
- Watch for Machine or Frame records in customs aggregators.
+54
View File
@@ -0,0 +1,54 @@
# Run Note: 2026-05-02
## Summary
- Full watch run completed with artifacts in `/Users/sean/Coding/steam-hardware-watch/runs/2026-05-02`.
- No new price or exact release-date signal was found for Steam Machine or Steam Frame.
- Steam Controller remains the only product with confirmed official price and exact purchase timing: `$99.00`, package `1558609`, purchase availability `May 4, 2026` at `10AM Pacific`.
- The May 2 comparison report is noisy because the May 1 artifact folder did not include the full Komodo/SteamTracking/asset coverage from the normal wrapper. Treat older Komodo sections listed as "added" as coverage deltas, not newly published sections.
## Source Checks
### Komodo
- Komodo API access worked.
- Controller product modified timestamp is now `2026-04-30T19:14:10`.
- Controller remains `purchasable` and `outofstock`, without `product_tag-wishlist-only`.
- Machine and Frame remain unchanged from `2026-04-24`, still `outofstock` and `product_tag-wishlist-only`, with no `purchasable` class.
- Visual asset retrieval completed: `141` discovered, `141` retrieved, `0` blocked.
### SteamDB
- Automated SteamDB helper remains blocked by challenge pages for the controller app, app history, unboxing app, and unboxing package.
- No fresh SteamDB metadata should be inferred from this run.
### SteamTracking / GameTracking
- Pairing and controller ecosystem strings remain present in `/tmp/SteamTracking-master`.
- Focused hits still include `ibex_internal`, `ibex_external`, `PairDongleTritonConnected`, `PairDongleTritonDocked`, and `ShouldTritonPairInOobe`.
- No material semantic delta was identified.
### Valve Support / CDN
- Official Valve pages and APIs were reachable.
- Appdetails and packagedetails still confirm Steam Controller at `$99.00`, package `1558609`, release date `May 4, 2026`.
- The controller store page still contains the `Available for purchase May 4th, 10AM Pacific` callout.
- Steam Controller store event metadata moved to `2026-05-01T23:18:58Z`; Steam Hardware root event metadata moved to `2026-05-01T22:43:47Z`.
- No comparable Machine or Frame price, purchase package, or exact timing surfaced.
### Customs / Regulatory
- Not rerun in this wrapper pass.
- Latest customs context remains the `2026-05-01` NBD and ImportGenius artifacts.
## Effect On Key Questions
- Price: unchanged. Controller confirmed at `$99.00`; Machine and Frame unknown.
- Release date: unchanged. Controller purchase availability remains `May 4, 2026` at `10AM Pacific`; Machine and Frame remain broad `2026`.
- Same-time launch: unchanged. Current evidence still favors a Controller-first launch.
## Next Checks
- Watch Machine and Frame Komodo records for removal of `product_tag-wishlist-only` or addition of `purchasable`.
- Recheck official Valve APIs and `/hardware/...` pages for Machine/Frame price or package exposure.
- Use browser-style SteamDB access if SteamDB state is needed before the May 4 controller sale window.
+68
View File
@@ -0,0 +1,68 @@
# Run Note: 2026-05-04
## Summary
- Full watch run completed with artifacts in `/Users/sean/Coding/steam-hardware-watch/runs/2026-05-04`.
- The strongest change is official Valve store metadata movement on launch day: Steam Controller and Steam Hardware events both moved at `2026-05-04T18:27Z`.
- Official appdetails and packagedetails still confirm Steam Controller package `1558609`, USD `$99.00`, and release date `May 4, 2026`.
- No new price or exact release-date signal was found for Steam Machine or Steam Frame.
- New SteamVR depot and SteamOS mirror helpers produced their first baseline reports. Treat their comparison entries as new-source coverage, not product movement.
## Source Checks
### Komodo
- Komodo API access was blocked. The comparison report's Komodo section removals are false deltas caused by missing current Komodo reports.
- Visual asset handling fell back to the known asset set: `141` discovered, `141` retrieved, `0` blocked.
### SteamDB
- SteamDB helper remained blocked by challenge pages for the controller app, app history, unboxing app, and unboxing package.
- No fresh SteamDB metadata should be inferred from this run.
### SteamTracking / GameTracking
- Fresh SteamTracking checkout still contains the known `ibex_internal`, `ibex_external`, `PairDongleTritonConnected`, `PairDongleTritonDocked`, and `ShouldTritonPairInOobe` pairing surface.
- The same Triton/Ibex pairing API names now appear in `Random/SteamApkStrings.txt`, broadening the client-surface evidence to the Steam Android APK string dump.
- No new price, package, or exact release-date signal appeared in SteamTracking.
### SteamVR Depots
- SteamVR app `250820` news metadata was saved.
- SteamDB's SteamVR depot page was blocked by a challenge page, so no fresh depot manifest/build comparison was collected.
- No local SteamVR install/depot snapshot was available, so this run did not inspect changed SteamVR JS/resources/drivers directly.
### SteamOS Package Mirror
- Public SteamOS mirror metadata was reachable.
- Default `holo`/`jupiter` package database extraction produced `758` package rows and no errors.
- No direct `Fremont`, `Deckard`, `Roy`, `Steam Frame`, `Steam Machine`, ARM/Snapdragon, or new product-specific top-level repo namespace appeared in the default pass.
- Notable hits remained Deck/Jupiter-adjacent: `foxnet`, `foxnetstatsd`, `linux-firmware-neptune-*`, and `plasma-remotecontrollers`.
### Valve Support / CDN
- Official Valve store pages were reachable.
- Steam Controller appdetails still show hardware type, package `1558609`, USD `$99.00`, and release date `May 4, 2026`.
- Steam Controller packagedetails still show final price `9900` cents USD and release date `May 4, 2026`.
- Steam Controller event metadata moved from `2026-05-01T23:18:58Z` to `2026-05-04T18:27:52Z`.
- Steam Hardware root event metadata moved from `2026-05-01T22:43:47Z` to `2026-05-04T18:27:56Z`.
- The event announcement body text hash did not change, so this looks like metadata/json movement rather than a clear public copy change.
- Steam Machine and Steam Frame still do not expose comparable price or exact availability.
### Customs / Regulatory
- Not rerun in this wrapper pass.
- Latest customs context remains the `2026-05-01` NBD and ImportGenius artifacts.
## Effect On Key Questions
- Price: unchanged. Controller confirmed at `$99.00`; Machine and Frame unknown.
- Release date: unchanged. Controller confirmed for `May 4, 2026`; Machine and Frame remain broad `2026`.
- Same-time launch: unchanged. Current evidence still favors a Controller-first launch.
## Next Checks
- Use browser-style SteamDB access if fresh SteamDB app/package state is important.
- Download SteamVR beta depot snapshots or set `STEAMVR_SCAN_DIRS` to a local SteamVR install/depot snapshot to inspect actual changed content.
- Recheck Komodo with a browser fallback if Machine/Frame product state is important.
- Monitor Valve store APIs and `/hardware/...` pages for Machine/Frame package, price, or exact timing.
+76
View File
@@ -0,0 +1,76 @@
# Run Note: 2026-05-10
## Summary
- Full watch run completed with artifacts in `/Users/sean/Coding/steam-hardware-watch/runs/2026-05-10`.
- Added the new SteamDB reservation-package monitor to the normal SteamDB helper before rerunning.
- SteamDB remained blocked, including through the dedicated browser fallback, so the SteamDB package TSV records `missing_or_blocked` for all watched package IDs.
- Valve Store APIs produced a clean public-readiness baseline: Controller is public at `$99.00`; Machine and Frame apps are public but still have no packages, package groups, or price.
## Source Checks
### Komodo
- Komodo API access worked.
- Product modified timestamps:
- Controller: `2026-05-08T15:55:26`
- Machine: `2026-04-24T14:32:54`
- Frame: `2026-04-24T14:33:36`
- Visual assets: `141` discovered, `141` retrieved, `0` blocked.
### SteamDB
- New reservation package report:
- `/Users/sean/Coding/steam-hardware-watch/runs/2026-05-10/reports/steamdb-reservation-packages.tsv`
- Watched package IDs:
- Controller: `1558609`
- Machine: `1629446`, `1629447`, `1629458`, `1629460`
- Frame: `1629484`, `1629486`
- All SteamDB fetches were blocked by challenge pages, including package pages and the previous app/history/unboxing checks.
- The report is useful as a monitor shape baseline, but not as a SteamDB content baseline.
### SteamTracking / GameTracking
- Pairing-focused hits remain present in `/tmp/SteamTracking-master`.
- Key strings include `ibex_internal`, `ibex_external`, `PairDongleTritonConnected`, `PairDongleTritonDocked`, and `ShouldTritonPairInOobe`.
- No new package-ID origin signal was found beyond the known `334bd31a28a0` baseline from `2026-04-28T23:46:34Z`.
### SteamVR Depots
- SteamVR news metadata was saved.
- SteamDB depot metadata was blocked.
- No local SteamVR depot snapshot was available for content scanning.
### SteamOS Package Mirror
- SteamOS mirror metadata was reachable.
- Notable hits include `fremont-hw-support 20260506.1-1` in `holo-3.8` and `holo-main`.
- No direct Machine, Frame, Deckard, Roy, ARM/Snapdragon, or new product-specific repo namespace appeared in the default pass.
### Valve Support / CDN
- Valve pages and APIs were reachable.
- Reservation package API snapshot:
- Controller app `4165870`: public, package `1558609`, package group present, `$99.00`.
- Frame app `4165890`: public app metadata, `Coming soon`, no packages, no package groups, no price.
- Machine app `4165910`: public app metadata, `Coming soon`, no packages, no package groups, no price.
- Machine package IDs `1629446`, `1629447`, `1629458`, `1629460`: private via `packagedetails success:false`.
- Frame package IDs `1629484`, `1629486`: private via `packagedetails success:false`.
### Customs / Regulatory
- ImportInfo customs fetches were blocked.
- No new customs rows were extracted.
- Latest useful customs context remains the `2026-05-01` NBD / ImportGenius evidence.
## Effect On Key Questions
- Price: unchanged. Controller confirmed at `$99.00`; Machine and Frame unknown.
- Release date: unchanged. Controller confirmed for `May 4, 2026`; Machine and Frame remain `Coming soon` / broad `2026`.
- Same-time launch: unchanged. Current evidence supports Controller-first availability, not a same-day trio launch.
## Next Checks
- Complete one trusted-browser SteamDB pass for the watched package pages.
- Watch Valve APIs for Machine/Frame package or package-group exposure.
- Continue normal checks next week with SteamDB package monitoring enabled.
+85
View File
@@ -0,0 +1,85 @@
# Run Note: 2026-05-11
## Summary
- Baseline run completed and repaired after refreshing the one-time Steam Guard code for SteamKit/PICS.
- SteamKit/PICS now gives the primary watched app/package changenumber baseline.
- No new public price, package group, purchase state, or exact availability signal appeared for Steam Machine or Steam Frame.
- SteamDB, customs, and the SteamDB-hosted SteamVR depot page were blocked in automated checks.
## Source Checks
### Komodo
- Komodo API access worked.
- Product modified timestamps:
- Controller: `2026-05-08T15:55:26`
- Machine: `2026-04-24T14:32:54`
- Frame: `2026-04-24T14:33:36`
- Visual asset retrieval completed: `141` discovered, `141` retrieved, `0` blocked.
### SteamKit / PICS
- SteamKit/PICS completed successfully after rerunning only this source against the saved run folder.
- Baseline changenumbers:
- Controller app `4165870`: `35731145`
- Frame app `4165890`: `35675573`
- Machine app `4165910`: `35675573`
- Controller package `1558609`: `35745078`
- Machine packages `1629446`, `1629447`, `1629458`, `1629460`: `35672615`
- Frame packages `1629484`, `1629486`: `35672606`
- Machine and Frame rows remain private / `missing_token`, but changenumbers are visible and suitable for future movement checks.
### SteamDB
- Automated SteamDB access was blocked by challenge pages.
- All watched package rows remain `missing_or_blocked` in the SteamDB TSV.
- SteamDB is now corroborating rather than primary because SteamKit/PICS covers direct package movement.
### SteamTracking / GameTracking
- Known Triton/Ibex controller pairing surface is still present:
- `ibex_internal`
- `ibex_external`
- `PairDongleTritonConnected`
- `PairDongleTritonDocked`
- `ShouldTritonPairInOobe`
- No new price or exact availability signal was found.
### SteamVR Depots
- SteamVR news metadata was saved.
- SteamDB's SteamVR depot page remained blocked, so no fresh depot manifest/build comparison was collected.
- No local SteamVR depot snapshot was available for deeper scanning.
### SteamOS Package Mirror
- SteamOS mirror metadata was reachable.
- Notable hits include `fremont-hw-support 20260506.1-1` in `holo-3.8` and `holo-main`.
- No direct Steam Frame, Steam Machine, Deckard, Roy, ARM/Snapdragon, or new product-specific repo namespace appeared in the default pass.
### Valve Support / CDN
- Official Valve APIs were reachable.
- Controller app `4165870` remains public with package `1558609`, package group present, and `$99.00`.
- Frame app `4165890` remains public metadata only: `Coming soon`, no packages, no package groups, no price.
- Machine app `4165910` remains public metadata only: `Coming soon`, no packages, no package groups, no price.
- Machine and Frame watched packages still return `packagedetails success:false`.
### Customs / Regulatory
- ImportInfo automated customs fetches were blocked.
- Latest useful customs evidence remains the `2026-05-01` NBD / ImportGenius pass.
## Effect On Key Questions
- Price: unchanged. Controller is confirmed at `$99.00`; Machine and Frame have no confirmed public price.
- Release date: unchanged. Controller is confirmed at `May 4, 2026`; Machine and Frame still only expose broad `Coming soon` / `2026` timing.
- Same-time launch: unchanged. Same-day trio availability is ruled out; Machine and Frame are still not public-ready in Valve package APIs.
## Next Checks
- Watch SteamKit/PICS changenumbers for all watched IDs on every normal run.
- Watch Valve `appdetails` / `packagedetails` for Machine and Frame package or package-group exposure.
- Get a trusted-browser SteamDB package-page baseline only if human-readable corroboration is needed.
- Continue Komodo, SteamTracking, SteamOS mirror, Valve API, and customs checks.
+111 -7
View File
@@ -88,6 +88,7 @@ class CheckSteamKitPicsTests(unittest.TestCase):
out_dir=""
report=""
key_lines=""
markdown=""
while [ "$#" -gt 0 ]; do
case "$1" in
--out-dir)
@@ -102,20 +103,25 @@ class CheckSteamKitPicsTests(unittest.TestCase):
shift
key_lines="$1"
;;
--markdown-report)
shift
markdown="$1"
;;
esac
shift || true
done
mkdir -p "$out_dir" "$(dirname "$report")" "$(dirname "$key_lines")"
mkdir -p "$out_dir" "$(dirname "$report")" "$(dirname "$key_lines")" "$(dirname "$markdown")"
printf '%s\\n' '{"packages":{"1629484":{"change_number":35500001}}}' > "$out_dir/pics-product-info.json"
{
printf '%s\\n' 'type product id status changenumber related_ids details'
printf '%s\\n' 'package Steam Frame 1629484 available 35500001 4165890 apps=4165890:Steam Frame'
printf '%s\\n' 'type product id status changenumber previous_changenumber changed_since_previous sha_hash only_public name related_ids details'
printf '%s\\n' 'package Steam Frame 1629484 available 35500001 35500000 yes abc123 False 4165890 apps=4165890:Steam Frame'
} > "$report"
{
printf '%s\\n' 'SteamKit/PICS package snapshot:'
printf '%s\\n' 'package Steam Frame 1629484 available 35500001 4165890 apps=4165890:Steam Frame'
printf '%s\\n' 'package Steam Frame 1629484 available 35500001 35500000 yes abc123 False 4165890 apps=4165890:Steam Frame'
} > "$key_lines"
printf '%s\\n' '# SteamKit / PICS Detail' > "$markdown"
""",
)
@@ -145,14 +151,106 @@ class CheckSteamKitPicsTests(unittest.TestCase):
dotnet_args = log_path.read_text(encoding="utf-8")
self.assertIn("run --project", dotnet_args)
self.assertIn("tools/steamkit-pics", dotnet_args)
self.assertIn("--markdown-report", dotnet_args)
report = (run_dir / "reports" / "steamkit-pics-packages.tsv").read_text(
encoding="utf-8"
)
self.assertIn("package\tSteam Frame\t1629484\tavailable\t35500001", report)
self.assertIn("previous_changenumber\tchanged_since_previous", report)
self.assertIn("package\tSteam Frame\t1629484\tavailable\t35500001\t35500000\tyes", report)
self.assertTrue(
(run_dir / "api" / "steamkit" / "pics-product-info.json").exists()
)
self.assertTrue((run_dir / "reports" / "steamkit-pics-detail.md").exists())
def test_passes_previous_report_when_prior_run_exists(self):
tmp = TemporaryDirectory()
self.addCleanup(tmp.cleanup)
tmp_path = Path(tmp.name)
previous_run = tmp_path / "2026-05-10"
run_dir = tmp_path / "2026-05-11"
previous_reports = previous_run / "reports"
previous_reports.mkdir(parents=True)
previous_report = previous_reports / "steamkit-pics-packages.tsv"
previous_report.write_text(
"type\tproduct\tid\tstatus\tchangenumber\tprevious_changenumber\tchanged_since_previous\tsha_hash\tonly_public\tname\trelated_ids\tdetails\n"
"package\tSteam Frame\t1629484\tprivate_metadata_token_required\t35500000\t\t\tabc122\tFalse\t\t\tapps=\n",
encoding="utf-8",
)
fake_bin = tmp_path / "bin"
fake_bin.mkdir()
log_path = tmp_path / "dotnet-args.log"
write_executable(
fake_bin / "dotnet",
"""
#!/bin/sh
printf '%s\\n' "$*" > "$FAKE_DOTNET_LOG"
previous=""
report=""
key_lines=""
markdown=""
out_dir=""
while [ "$#" -gt 0 ]; do
case "$1" in
--previous-report)
shift
previous="$1"
;;
--out-dir)
shift
out_dir="$1"
;;
--report)
shift
report="$1"
;;
--key-lines)
shift
key_lines="$1"
;;
--markdown-report)
shift
markdown="$1"
;;
esac
shift || true
done
test -s "$previous" || exit 11
mkdir -p "$out_dir" "$(dirname "$report")" "$(dirname "$key_lines")" "$(dirname "$markdown")"
printf '%s\\n' '{}' > "$out_dir/pics-product-info.json"
printf '%s\\n' 'type product id status changenumber previous_changenumber changed_since_previous sha_hash only_public name related_ids details' > "$report"
printf '%s\\n' 'SteamKit/PICS package snapshot:' > "$key_lines"
printf '%s\\n' '# SteamKit / PICS Detail' > "$markdown"
""",
)
env = os.environ.copy()
env.update(
{
"PATH": f"{fake_bin}:{env['PATH']}",
"STEAMKIT_ENV_FILE": str(tmp_path / "missing-env.sh"),
"STEAMKIT_USERNAME": "watcher",
"STEAMKIT_PASSWORD": "secret",
"FAKE_DOTNET_LOG": str(log_path),
}
)
result = subprocess.run(
[str(ROOT / "scripts" / "check_steamkit_pics.sh"), str(run_dir)],
cwd=ROOT,
env=env,
text=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
check=False,
)
self.assertEqual("", result.stderr)
self.assertEqual(0, result.returncode)
dotnet_args = log_path.read_text(encoding="utf-8")
self.assertIn("--previous-report", dotnet_args)
self.assertIn(str(previous_report), dotnet_args)
def test_exports_credentials_loaded_from_local_env_file_to_dotnet_helper(self):
tmp = TemporaryDirectory()
@@ -184,6 +282,7 @@ class CheckSteamKitPicsTests(unittest.TestCase):
out_dir=""
report=""
key_lines=""
markdown=""
while [ "$#" -gt 0 ]; do
case "$1" in
--out-dir)
@@ -198,14 +297,19 @@ class CheckSteamKitPicsTests(unittest.TestCase):
shift
key_lines="$1"
;;
--markdown-report)
shift
markdown="$1"
;;
esac
shift || true
done
mkdir -p "$out_dir" "$(dirname "$report")" "$(dirname "$key_lines")"
mkdir -p "$out_dir" "$(dirname "$report")" "$(dirname "$key_lines")" "$(dirname "$markdown")"
printf '%s\\n' '{}' > "$out_dir/pics-product-info.json"
printf '%s\\n' 'type product id status changenumber related_ids details' > "$report"
printf '%s\\n' 'SteamKit/PICS package snapshot:' > "$key_lines"
printf '%s\\n' '# SteamKit / PICS Detail' > "$markdown"
""",
)
@@ -246,7 +350,7 @@ class SteamKitSummaryTests(unittest.TestCase):
reports.mkdir(parents=True)
(reports / "steamkit-pics-key-lines.txt").write_text(
"SteamKit/PICS package snapshot:\n"
"package\tSteam Frame\t1629484\tavailable\t35500001\t4165890\tapps=4165890:Steam Frame\n",
"package\tSteam Frame\t1629484\tprivate_metadata_token_required\t35500001\t35500000\tyes\tabc123\tFalse\t\t4165890\tapps=4165890:Steam Frame\n",
encoding="utf-8",
)
(reports / "steamkit-pics-errors.txt").write_text("", encoding="utf-8")
+35
View File
@@ -0,0 +1,35 @@
import shutil
import subprocess
import unittest
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
class RunStorageTests(unittest.TestCase):
def test_init_run_defaults_to_gitignored_repo_runs_directory(self):
run_date = "2099-01-02"
run_dir = ROOT / "runs" / run_date
run_note = ROOT / "status" / "runs" / f"{run_date}.md"
self.addCleanup(lambda: shutil.rmtree(run_dir, ignore_errors=True))
self.addCleanup(lambda: run_note.unlink(missing_ok=True))
result = subprocess.run(
[str(ROOT / "scripts" / "init_run.sh"), run_date],
cwd=ROOT,
text=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
check=False,
)
self.assertEqual("", result.stderr)
self.assertEqual(0, result.returncode)
self.assertIn(f"RUN_DIR={run_dir}", result.stdout)
self.assertTrue((run_dir / "api").is_dir())
self.assertTrue((run_dir / "reports").is_dir())
if __name__ == "__main__":
unittest.main()
+1 -1
View File
@@ -226,7 +226,7 @@ class SaveVisualAssetsTests(unittest.TestCase):
{"title": "videoframe_789", "slug": "videoframe_789", "parent_id": ""},
"https://komodostation.com/wp-content/uploads/2026/04/videoframe_789-1024x576.png",
{
"/Users/sean/steam_hardware_watch/2026-04-26/api/komodo/media-parent-section-433306.json"
"/Users/sean/Coding/steam-hardware-watch/runs/2026-04-26/api/komodo/media-parent-section-433306.json"
},
),
)
+260 -32
View File
@@ -6,6 +6,7 @@ var options = Args.Parse(args);
Directory.CreateDirectory(options.OutDir);
Directory.CreateDirectory(Path.GetDirectoryName(options.ReportPath) ?? ".");
Directory.CreateDirectory(Path.GetDirectoryName(options.KeyLinesPath) ?? ".");
Directory.CreateDirectory(Path.GetDirectoryName(options.MarkdownReportPath) ?? ".");
var username = Env("STEAMKIT_USERNAME");
var password = Env("STEAMKIT_PASSWORD");
@@ -36,18 +37,24 @@ await File.WriteAllTextAsync(
cts.Token
);
var rows = ReportRows.Build(snapshot);
await File.WriteAllLinesAsync(options.ReportPath, rows.Select(row => string.Join('\t', row.Select(CleanTsv))), cts.Token);
var previous = PreviousRows.Load(options.PreviousReportPath);
var rows = ReportRows.Build(snapshot, previous);
await File.WriteAllLinesAsync(
options.ReportPath,
new[] { ReportRow.HeaderLine() }.Concat(rows.Select(row => row.ToTsv())),
cts.Token
);
var keyLines = new List<string> { "SteamKit/PICS package snapshot:" };
keyLines.AddRange(rows.Take(40).Select(row => string.Join('\t', row.Select(CleanTsv))));
keyLines.Add(ReportRow.HeaderLine());
keyLines.AddRange(rows.Take(40).Select(row => row.ToTsv()));
await File.WriteAllLinesAsync(options.KeyLinesPath, keyLines, cts.Token);
await File.WriteAllTextAsync(options.MarkdownReportPath, MarkdownReport.Build(snapshot, rows, options.PreviousReportPath), cts.Token);
static string? Env(string name) => Environment.GetEnvironmentVariable(name);
static string CleanTsv(string? value) => (value ?? "").Replace('\t', ' ').Replace('\n', ' ').Trim();
sealed record Args(string OutDir, string ReportPath, string KeyLinesPath)
sealed record Args(string OutDir, string ReportPath, string KeyLinesPath, string MarkdownReportPath, string? PreviousReportPath)
{
public static Args Parse(string[] args)
{
@@ -70,7 +77,11 @@ sealed record Args(string OutDir, string ReportPath, string KeyLinesPath)
return new Args(
Require(values, "--out-dir"),
Require(values, "--report"),
Require(values, "--key-lines")
Require(values, "--key-lines"),
Require(values, "--markdown-report"),
values.TryGetValue("--previous-report", out var previousReport) && !string.IsNullOrWhiteSpace(previousReport)
? previousReport
: null
);
}
@@ -302,35 +313,132 @@ sealed record KeyValueNode(string Name, string? Value, List<KeyValueNode> Childr
}
}
sealed record PreviousRow(string ChangeNumber);
static class PreviousRows
{
public static Dictionary<string, PreviousRow> Load(string? path)
{
if (string.IsNullOrWhiteSpace(path) || !File.Exists(path))
{
return new Dictionary<string, PreviousRow>(StringComparer.Ordinal);
}
var lines = File.ReadAllLines(path);
if (lines.Length == 0)
{
return new Dictionary<string, PreviousRow>(StringComparer.Ordinal);
}
var header = lines[0].Split('\t');
var typeIndex = Array.IndexOf(header, "type");
var idIndex = Array.IndexOf(header, "id");
var changeIndex = Array.IndexOf(header, "changenumber");
if (typeIndex < 0 || idIndex < 0 || changeIndex < 0)
{
return new Dictionary<string, PreviousRow>(StringComparer.Ordinal);
}
var result = new Dictionary<string, PreviousRow>(StringComparer.Ordinal);
foreach (var line in lines.Skip(1))
{
if (string.IsNullOrWhiteSpace(line))
{
continue;
}
var parts = line.Split('\t');
if (parts.Length <= Math.Max(typeIndex, Math.Max(idIndex, changeIndex)))
{
continue;
}
result[$"{parts[typeIndex]}:{parts[idIndex]}"] = new PreviousRow(parts[changeIndex]);
}
return result;
}
}
sealed record ReportRow(
string Type,
string Product,
string Id,
string Status,
string ChangeNumber,
string PreviousChangeNumber,
string ChangedSincePrevious,
string ShaHash,
string OnlyPublic,
string Name,
string RelatedIds,
string Details)
{
public static string HeaderLine()
=> string.Join('\t', new[]
{
"type",
"product",
"id",
"status",
"changenumber",
"previous_changenumber",
"changed_since_previous",
"sha_hash",
"only_public",
"name",
"related_ids",
"details",
});
public string ToTsv()
=> string.Join('\t', new[]
{
Type,
Product,
Id,
Status,
ChangeNumber,
PreviousChangeNumber,
ChangedSincePrevious,
ShaHash,
OnlyPublic,
Name,
RelatedIds,
Details,
}.Select(Tsv.Clean));
}
static class Tsv
{
public static string Clean(string? value) => (value ?? "").Replace('\t', ' ').Replace('\n', ' ').Trim();
}
static class ReportRows
{
public static List<string[]> Build(PicsSnapshot snapshot)
public static List<ReportRow> Build(PicsSnapshot snapshot, Dictionary<string, PreviousRow> previous)
{
var rows = new List<string[]>
{
new[] { "type", "product", "id", "status", "changenumber", "related_ids", "details" },
};
var rows = new List<ReportRow>();
foreach (var (id, product) in Targets.Apps.OrderBy(pair => pair.Key))
{
var key = id.ToString();
rows.Add(snapshot.Apps.TryGetValue(key, out var info)
? AppRow(product, info)
: MissingRow("app", product, id, snapshot.UnknownApps.Contains(id) ? "unknown" : "missing"));
? AppRow(product, info, previous)
: MissingRow("app", product, id, snapshot.UnknownApps.Contains(id) ? "unknown" : "missing", previous));
}
foreach (var (id, product) in Targets.Packages.OrderBy(pair => pair.Key))
{
var key = id.ToString();
rows.Add(snapshot.Packages.TryGetValue(key, out var info)
? PackageRow(product, info)
: MissingRow("package", product, id, snapshot.UnknownPackages.Contains(id) ? "unknown" : "missing"));
? PackageRow(product, info, previous)
: MissingRow("package", product, id, snapshot.UnknownPackages.Contains(id) ? "unknown" : "missing", previous));
}
return rows;
}
static string[] AppRow(string product, ProductInfo info)
static ReportRow AppRow(string product, ProductInfo info, Dictionary<string, PreviousRow> previous)
{
var name = info.KeyValues?.Path("common", "name") ?? "";
var depotIds = info.KeyValues?.Child("depots")?.Children
@@ -338,44 +446,164 @@ static class ReportRows
.Select(child => child.Name)
.Order()
.ToArray() ?? Array.Empty<string>();
var branchCount = info.KeyValues?.Child("depots")?.Child("branches")?.Children.Count ?? 0;
var status = info.MissingToken ? "missing_token" : "available";
var details = $"name={name}; depots={depotIds.Length}; branches={branchCount}; only_public={info.OnlyPublic}";
var branches = info.KeyValues?.Child("depots")?.Child("branches")?.Children ?? new List<KeyValueNode>();
var branchNames = branches.Select(branch => branch.Name).Where(name => !string.IsNullOrWhiteSpace(name)).Order().ToArray();
var branchBuildIds = branches
.Select(branch => (branch.Name, BuildId: branch.Path("buildid")))
.Where(branch => !string.IsNullOrWhiteSpace(branch.Name) && !string.IsNullOrWhiteSpace(branch.BuildId))
.Select(branch => $"{branch.Name}:{branch.BuildId}")
.Order()
.ToArray();
var status = info.MissingToken ? "private_metadata_token_required" : "available";
var details = $"depots_count={depotIds.Length}; branch_names={string.Join(",", branchNames)}; branch_buildids={string.Join(",", branchBuildIds)}";
return new[]
{
return WithPrevious(
"app",
product,
info.Id.ToString(),
status,
info.ChangeNumber.ToString(),
info.ShaHash ?? "",
info.OnlyPublic.ToString(),
name,
string.Join(",", depotIds),
details,
};
previous
);
}
static string[] PackageRow(string product, ProductInfo info)
static ReportRow PackageRow(string product, ProductInfo info, Dictionary<string, PreviousRow> previous)
{
var appIds = info.KeyValues?.Child("appids")?.Children
.Select(child => child.Name)
.Where(name => uint.TryParse(name, out _))
.Order()
.ToArray() ?? Array.Empty<string>();
var status = info.MissingToken ? "missing_token" : "available";
var details = $"apps={string.Join(",", appIds)}; only_public={info.OnlyPublic}";
var name = info.KeyValues?.Path("name") ?? info.KeyValues?.Path("common", "name") ?? "";
var status = info.MissingToken ? "private_metadata_token_required" : "available";
var details = $"apps_count={appIds.Length}";
return new[]
{
return WithPrevious(
"package",
product,
info.Id.ToString(),
status,
info.ChangeNumber.ToString(),
info.ShaHash ?? "",
info.OnlyPublic.ToString(),
name,
string.Join(",", appIds),
details,
};
previous
);
}
static string[] MissingRow(string type, string product, uint id, string status)
=> new[] { type, product, id.ToString(), status, "", "", "PICS product info was not returned" };
static ReportRow MissingRow(string type, string product, uint id, string status, Dictionary<string, PreviousRow> previous)
=> WithPrevious(type, product, id.ToString(), status, "", "", "", "", "", "PICS product info was not returned", previous);
static ReportRow WithPrevious(
string type,
string product,
string id,
string status,
string changeNumber,
string shaHash,
string onlyPublic,
string name,
string relatedIds,
string details,
Dictionary<string, PreviousRow> previous)
{
previous.TryGetValue($"{type}:{id}", out var previousRow);
var previousChange = previousRow?.ChangeNumber ?? "";
var changed = "";
if (!string.IsNullOrWhiteSpace(changeNumber))
{
changed = string.IsNullOrWhiteSpace(previousChange)
? "new"
: previousChange == changeNumber ? "no" : "yes";
}
return new ReportRow(type, product, id, status, changeNumber, previousChange, changed, shaHash, onlyPublic, name, relatedIds, details);
}
}
static class MarkdownReport
{
public static string Build(PicsSnapshot snapshot, List<ReportRow> rows, string? previousReportPath)
{
var lines = new List<string>
{
"# SteamKit / PICS Detail",
"",
$"Fetched at UTC: `{snapshot.FetchedAtUtc:O}`",
"",
"SteamKit/PICS is the direct Steam metadata check. A `private_metadata_token_required` status means Steam returned the product shell and changenumber but withheld private product details without a PICS token. For this project, that is still useful as a movement signal, not a public-readiness signal.",
"",
};
if (!string.IsNullOrWhiteSpace(previousReportPath))
{
lines.Add($"Previous report: `{previousReportPath}`");
lines.Add("");
}
var changedRows = rows.Where(row => row.ChangedSincePrevious is "yes" or "new").ToList();
lines.Add("## Changenumber Movement");
lines.Add("");
if (changedRows.Count == 0)
{
lines.Add("- No watched SteamKit/PICS changenumber movement versus the previous report.");
}
else
{
lines.AddRange(changedRows.Select(row =>
$"- `{row.Type}` `{row.Product}` `{row.Id}`: `{row.PreviousChangeNumber}` -> `{row.ChangeNumber}` (`{row.Status}`)"
));
}
lines.Add("");
lines.Add("## Watched Products");
lines.Add("");
foreach (var product in rows.Select(row => row.Product).Distinct().Order())
{
lines.Add($"### {product}");
lines.Add("");
foreach (var row in rows.Where(row => row.Product == product).OrderBy(row => row.Type).ThenBy(row => row.Id))
{
var interpretation = row.Status == "available"
? "metadata available"
: row.Status == "private_metadata_token_required"
? "movement signal only; private metadata is withheld"
: "unavailable in this run";
lines.Add($"- `{row.Type}` `{row.Id}`: changenumber `{row.ChangeNumber}`, previous `{row.PreviousChangeNumber}`, changed `{row.ChangedSincePrevious}`, status `{row.Status}` ({interpretation}).");
if (!string.IsNullOrWhiteSpace(row.Name))
{
lines.Add($" Name: `{row.Name}`.");
}
if (!string.IsNullOrWhiteSpace(row.RelatedIds))
{
lines.Add($" Related IDs: `{row.RelatedIds}`.");
}
if (!string.IsNullOrWhiteSpace(row.ShaHash))
{
lines.Add($" SHA hash: `{row.ShaHash}`.");
}
if (!string.IsNullOrWhiteSpace(row.Details))
{
lines.Add($" Details: `{row.Details}`.");
}
}
lines.Add("");
}
lines.Add("## Raw Outputs");
lines.Add("");
lines.Add("- Raw JSON: `api/steamkit/pics-product-info.json`");
lines.Add("- Compact TSV: `reports/steamkit-pics-packages.tsv`");
lines.Add("");
return string.Join(Environment.NewLine, lines);
}
}