Skip to content

fix(adapters): drop silent-sentinel row fallbacks across Apple Podcasts, Reddit, and Gitee#1634

Merged
jackwener merged 3 commits into
jackwener:mainfrom
Benjamin-eecs:chore/silent-sentinel-cluster-3
May 18, 2026
Merged

fix(adapters): drop silent-sentinel row fallbacks across Apple Podcasts, Reddit, and Gitee#1634
jackwener merged 3 commits into
jackwener:mainfrom
Benjamin-eecs:chore/silent-sentinel-cluster-3

Conversation

@Benjamin-eecs
Copy link
Copy Markdown
Contributor

@Benjamin-eecs Benjamin-eecs commented May 17, 2026

Description

Continues the audit-baseline cleanup from #1611 (lesswrong) and #1631 (wikipedia / 36kr / xiaoyuzhou / zhihu), aligned with the direction set by 7164615 (silent-empty-fallback resolutions across Douyin / Jike / WeRead) and ee54eb8 (ignore sentinels in thrown errors).

Replaces silent-sentinel row fallbacks with the empty-string signal so agents can tell apart "field has the literal value Unknown" from "upstream returned no value".

Type of Change

  • 🐛 Bug fix
  • ✨ New feature
  • 🌐 New site adapter
  • 📝 Documentation
  • ♻️ Refactor
  • 🔧 CI / build / tooling

Checklist

  • I ran the checks relevant to this PR
  • I updated tests or docs if needed
  • I included output or screenshots when useful

Fix

Adapter Field Pattern
apple-podcasts/search episodes, genre ?? '-' to ?? ''
reddit/saved title || '-' to || ''
reddit/upvoted title || '-' to || ''
gitee/search language, description || '-' to || ''

All four files audited for downstream sentinel checks (grep -nE "=== ?['\"](Unknown|unknown|-)['\"]"); none reference the swapped values in control flow. This is the audit step that caught the v2ex/me.js regression in #1631 before merge.

Intentionally skipped

  • gitee/trending.js:272: downstream project.description !== '-' check drives the mergedDescription fallback. Same control-flow sentinel pattern as v2ex/me.js. Stays on baseline.
  • web/read.js (4 entries): '-' lives inside lines.push(...) rendered diagnostic text, not row fields. Empty would render with doubled spaces.
  • yollomi/{edit,video}.js (6 entries): file: '-', size: '-', credits: '-' are user-facing status rows. Empty would collapse columns visually.
  • zsxq/dynamics.js:31: title: '[${d.action || 'unknown'}]' is a template-literal-rendered title prefix. Empty would render [].

Screenshots / Output

Smoke test on two of the touched commands (read-only, public):

$ opencli apple-podcasts search "lex fridman" --limit 2 -f json
[
  {
    "id": 1434243584,
    "title": "Lex Fridman Podcast",
    "author": "Lex Fridman",
    "episodes": 497,
    "genre": "Technology",
    "url": "https://podcasts.apple.com/us/podcast/lex-fridman-podcast/id1434243584?uo=4"
  },
  {
    "id": 1567129969,
    "title": "Lex Fridman Podcast | 5 minute podcast summaries",
    "author": "5 minute podcast summaries",
    "episodes": 18,
    "genre": "Technology",
    "url": "https://podcasts.apple.com/us/podcast/lex-fridman-podcast-5-minute-podcast-summaries/id1567129969?uo=4"
  }
]

$ opencli gitee search "vue" --limit 2 -f json
[
  {
    "rank": 1,
    "name": "XE/vxe-table",
    "language": "TypeScript",
    "description": "vxe table 支持 vue2, vue3 的表格解决方案",
    "stars": "5160",
    "url": "https://gitee.com/x-extends/vxe-table"
  },
  {
    "rank": 2,
    "name": "有来开源/vue3-element-admin",
    "language": "Vue",
    "description": "🔥Vue3 + Vite 8+ TypeScript + Element-Plus 构建的后台管理前端模板,配套官方 Java 和 Node 后端源码,vue-element-admin 的 Vue3 版本。",
    "stars": "5843",
    "url": "https://gitee.com/youlaiorg/vue3-element-admin"
  }
]

These outputs come from the v1.7.22 published code path; populated rows are byte-identical between the published code and this PR. The empty-signal path only fires when the upstream API returns a null or missing field (trackCount, primaryGenreName, c.data.title, c.data.body, fields.langs, fields.description), which doesn't surface in the public-API samples above.

Test plan

  • npm run build: manifest compiles, no path leaks (git diff cli-manifest.json empty)
  • npm run check:typed-error-lint: passes (current=167, baseline=167, new=0, resolved=0)
  • npm run check:silent-column-drop: passes
  • Smoke test: opencli apple-podcasts search and opencli gitee search still return populated rows (populated-row path is byte-identical to this PR; not a direct exercise of the changed fallback).
  • Downstream sentinel audit: grep -nE "=== ?['\"](-|unknown|Unknown)['\"]" across the 4 touched files returns zero hits, so the swapped value is never consumed as a control-flow marker.
  • reddit/{saved,upvoted} smoke test omitted (requires logged-in reddit session on this machine); the diff is the same || '-' to || '' shape as the audited apple-podcasts / gitee files and downstream-sentinel grep is clean.

Copilot AI review requested due to automatic review settings May 17, 2026 08:51
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Continues a series of cleanups replacing silent sentinel row fallbacks ('-') with the empty-string signal so downstream consumers can distinguish a literal - value from an upstream-missing field. Updates the typed-error lint baseline accordingly.

Changes:

  • Replace ?? '-' / || '-' with ?? '' / || '' in 4 adapter files (apple-podcasts/search, reddit/saved, reddit/upvoted, gitee/search).
  • Remove the corresponding 6 entries from scripts/typed-error-lint-baseline.json.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.

Show a summary per file
File Description
clis/apple-podcasts/search.js Swap '-' sentinel to '' for episodes & genre
clis/reddit/upvoted.js Swap '-' sentinel to '' for title
clis/reddit/saved.js Swap '-' sentinel to '' for title
clis/gitee/search.js Swap '-' sentinel to '' for language & description
scripts/typed-error-lint-baseline.json Remove the 6 cleared baseline entries

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@Benjamin-eecs Benjamin-eecs force-pushed the chore/silent-sentinel-cluster-3 branch from 1647dab to 40b0ed8 Compare May 18, 2026 13:54
…ts, Reddit, and Gitee

Continues the audit-baseline cleanup from jackwener#1611 (lesswrong) and jackwener#1631
(wikipedia / 36kr / xiaoyuzhou / zhihu), and follows the direction set
by 7164615 (silent-empty-fallback resolutions across Douyin / Jike /
WeRead) and ee54eb8 (ignore sentinels in thrown errors).

Replaces silent-sentinel row fallbacks with the empty-string signal so
agents can tell apart "field has value Unknown" from "upstream returned
no value":

- apple-podcasts/search: episodes, genre
- reddit/saved: title
- reddit/upvoted: title
- gitee/search: language, description

All four files audited for downstream sentinel checks via
`grep -nE "=== ?['\"](Unknown|unknown|-)['\"]"`. None reference the
swapped values in control flow (verified against the v2ex/me.js class
of regression caught in jackwener#1631).

Intentionally skipped in this batch (will not flip to empty):
- gitee/trending.js:272: downstream `project.description !== '-'`
  check drives the mergedDescription fallback. Same control-flow
  sentinel pattern as v2ex/me.js. Stays on baseline.
- web/read.js x4: `'-'` lives inside rendered diagnostic lines
  (`lines.push(...)`), not row fields. Empty would render
  `  GET    /a/b` with a doubled space. UX placeholder.
- yollomi/{edit,video}.js x6: `file: '-'`, `size: '-'`, `credits: '-'`
  are user-facing status rows displayed to humans. Empty would
  collapse columns visually.
- zsxq/dynamics.js: `title: '[${d.action || 'unknown'}]'` is a
  template-literal-rendered title prefix. Empty would render `[]`.

Verified live: `opencli apple-podcasts search "lex fridman" --limit 2`
returns populated episodes/genre. `opencli gitee search "vue" --limit 2`
returns populated language/description. Baseline shrinks accordingly.
…swap

Mirrors the cluster-2 test additions, pairing the sentinel value swap
in this PR with focused unit tests that mock the upstream to return
null / missing fields and assert the row surfaces an empty-string
signal instead of the old fabricated '-' / 'unknown' sentinel.

Coverage:

- clis/apple-podcasts/commands.test.js (+1 case): stubs the iTunes
  Search response with a result that has collectionId / collectionName
  / artistName populated but no trackCount and no primaryGenreName.
  Asserts episodes and genre render as '' (was '-' before this PR).

- clis/gitee/search.test.js (new): mocks Gitee's `so.gitee.com/v1/search`
  fetch with two cases - a hit that has only title + url (no langs,
  no description), and a hit that has all fields populated. Asserts
  the missing fields render as '' (was '-' before) and that populated
  fields pass through verbatim.

The reddit/saved and reddit/upvoted changes in this PR live inside a
page.evaluate template literal that fetches from reddit.com inside
the browser context, so the empty-signal branch is executed inside
the page rather than in adapter JS. They are 1-char `|| '-'` ->
`|| ''` swaps with no downstream sentinel consumer and the same JS
semantics demonstrated by the gitee + apple-podcasts tests above.
The previous rebase left a stale linkedin/people-search entry in
cli-manifest.json that was carried over from a sibling feature branch.
This branch does not include the people-search source file, so the
entry was an orphan; CI's build-manifest safety check correctly
refused to overwrite it. Regenerating with --allow-removals to drop
the orphaned entry, after which a normal `npm run build` is a no-op.
@Benjamin-eecs Benjamin-eecs force-pushed the chore/silent-sentinel-cluster-3 branch from 2ff99c3 to 5b565c9 Compare May 18, 2026 15:02
@jackwener jackwener merged commit 40592ea into jackwener:main May 18, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants