{"id":"2e73193f-9edc-4300-b251-4ad26d72887c","entityType":"agent","slug":"clawhub-lenpr-audible-goodreads-deal-scout","name":"Audible Deal Scout","canonicalUrl":"https://www.xpersona.co/agent/clawhub-lenpr-audible-goodreads-deal-scout","canonicalPath":"/agent/clawhub-lenpr-audible-goodreads-deal-scout","generatedAt":"2026-10-10T07:08:11.544Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T03:37:29.815Z","emptyReason":null},"description":"Evaluate an Audible daily promotion against Goodreads public score, optional Goodreads CSV shelves, optional freeform reading notes, optional delivery rules,...","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1.7K downloads reported by the source. Last updated 10/10/2026.","installCommand":"clawhub skill install s1793ns2ngcn6emb53xdgbawts856yaf:audible-goodreads-deal-scout","sourceUrl":"https://clawhub.ai/lenpr/audible-goodreads-deal-scout","homepage":"https://clawhub.ai/lenpr/skills/audible-goodreads-deal-scout","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/lenpr/audible-goodreads-deal-scout","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/lenpr/skills/audible-goodreads-deal-scout","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":65,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"Audible Deal Scout technical dossier on Xpersona with agent coverage, OPENCLEW support, and live trust metadata."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-10T03:37:29.815Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T03:37:29.815Z","emptyReason":null},"stars":null,"forks":null,"downloads":1726,"packageName":null,"latestVersion":"0.1.18","tractionLabel":"1.7K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T03:37:29.815Z","emptyReason":null},"lastUpdatedAt":"2026-10-10T03:37:29.815Z","lastCrawledAt":"2026-10-10T03:37:29.815Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-11T03:37:29.815Z","lastVerifiedAt":null,"highlights":[{"version":"0.1.18","createdAt":"2026-07-20T03:29:40.028Z","changelog":"Harden scheduled execution, auth, config, scans, and release validation.","fileCount":32,"zipByteSize":113377},{"version":"0.1.17","createdAt":"2026-07-19T20:31:58.493Z","changelog":"Test release pointer after 0.1.16 publication.","fileCount":31,"zipByteSize":107373},{"version":"0.1.16","createdAt":"2026-07-19T20:28:13.176Z","changelog":"Reconcile cron timezone and configured delivery routing.","fileCount":31,"zipByteSize":107487},{"version":"0.1.14","createdAt":"2026-05-25T20:24:07.894Z","changelog":"Harden OpenClaw CLI discovery, add installed-version diagnostics, and surface disabled cron jobs.","fileCount":31,"zipByteSize":105861},{"version":"0.1.13","createdAt":"2026-05-04T20:33:10.598Z","changelog":"Constrain optional Audible auth use to token refresh and product-price lookup, add credential boundary metadata, and clarify auth trust docs.","fileCount":30,"zipByteSize":103485},{"version":"0.1.12","createdAt":"2026-05-04T17:45:25.130Z","changelog":"Add Audible URL guardrails, live fetch diagnostics, and fetch/test refactors.","fileCount":30,"zipByteSize":102039},{"version":"0.1.11","createdAt":"2026-04-29T11:50:51.800Z","changelog":"Prevent stale scheduled delivery artifacts after failed prep and harden Audible daily-promotion fetches.","fileCount":30,"zipByteSize":90865},{"version":"0.1.10","createdAt":"2026-04-29T11:17:35.946Z","changelog":"Add trust and data-access documentation, no-purchase disclosures, and release audit guidance.","fileCount":30,"zipByteSize":89308}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s1793ns2ngcn6emb53xdgbawts856yaf:audible-goodreads-deal-scout","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s1793ns2ngcn6emb53xdgbawts856yaf:audible-goodreads-deal-scout` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/lenpr/audible-goodreads-deal-scout before using production credentials."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-lenpr-audible-goodreads-deal-scout/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-lenpr-audible-goodreads-deal-scout/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-lenpr-audible-goodreads-deal-scout/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-lenpr-audible-goodreads-deal-scout/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-lenpr-audible-goodreads-deal-scout/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-lenpr-audible-goodreads-deal-scout/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-10T07:08:11.527Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-lenpr-audible-goodreads-deal-scout/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-lenpr-audible-goodreads-deal-scout/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-lenpr-audible-goodreads-deal-scout/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-lenpr-audible-goodreads-deal-scout/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T03:37:29.815Z","emptyReason":null},"readme":"Skill: Audible Deal Scout\n\nOwner: lenpr\n\nSummary: Evaluate an Audible daily promotion against Goodreads public score, optional Goodreads CSV shelves, optional freeform reading notes, optional delivery rules,...\n\nTags: latest:0.1.18, stable:0.1.13\n\nVersion history:\n\nv0.1.18 | 2026-07-20T03:29:40.028Z | user\n\nHarden scheduled execution, auth, config, scans, and release validation.\n\nv0.1.17 | 2026-07-19T20:31:58.493Z | user\n\nTest release pointer after 0.1.16 publication.\n\nv0.1.16 | 2026-07-19T20:28:13.176Z | user\n\nReconcile cron timezone and configured delivery routing.\n\nv0.1.14 | 2026-05-25T20:24:07.894Z | user\n\nHarden OpenClaw CLI discovery, add installed-version diagnostics, and surface disabled cron jobs.\n\nv0.1.13 | 2026-05-04T20:33:10.598Z | user\n\nConstrain optional Audible auth use to token refresh and product-price lookup, add credential boundary metadata, and clarify auth trust docs.\n\nv0.1.12 | 2026-05-04T17:45:25.130Z | user\n\nAdd Audible URL guardrails, live fetch diagnostics, and fetch/test refactors.\n\nv0.1.11 | 2026-04-29T11:50:51.800Z | user\n\nPrevent stale scheduled delivery artifacts after failed prep and harden Audible daily-promotion fetches.\n\nv0.1.10 | 2026-04-29T11:17:35.946Z | user\n\nAdd trust and data-access documentation, no-purchase disclosures, and release audit guidance.\n\nv0.1.9 | 2026-04-29T10:48:35.931Z | user\n\nImprove the ClawHub-visible skill overview while preserving agent runtime instructions.\n\nv0.1.8 | 2026-04-29T10:43:58.863Z | user\n\nRefresh ClawHub README and release metadata.\n\nv0.1.7 | 2026-04-29T10:40:17.789Z | user\n\nImprove README onboarding, setup next-step guidance, Want-to-Read scan UX, price/deal classification, Goodreads rating enrichment, Audible fetch robustness, and release polish.\n\nv0.1.6 | 2026-04-25T11:00:16.200Z | user\n\nImprove Want-to-Read scan progress, dedupe, and docs\n\nv0.1.5 | 2026-04-24T19:28:52.285Z | user\n\nAdd diagnostics, auth status, and authenticated scan UX hardening\n\nv0.1.4 | 2026-04-24T18:49:43.510Z | user\n\nAdd optional headless authenticated Audible price lookup\n\nv0.1.3 | 2026-04-22T19:04:15.467Z | user\n\nInvoke the published shell wrapper through sh so official OpenClaw installs still work even when the installed script loses its executable bit.\n\nv0.1.2 | 2026-04-22T17:47:39.520Z | user\n\nRename published wrapper and license files for ClawHub packaging\n\nv0.1.1 | 2026-04-22T17:39:17.137Z | user\n\nMove published wrapper entrypoint into scripts\n\nv0.1.0 | 2026-04-22T17:26:47.481Z | user\n\nInitial public release\n\nArchive index:\n\nArchive v0.1.18: 32 files, 113377 bytes\n\nFiles: agents/openai.yaml (317b), audible_goodreads_deal_scout/__init__.py (230b), audible_goodreads_deal_scout/audible_auth.py (26968b), audible_goodreads_deal_scout/audible_catalog.py (32405b), audible_goodreads_deal_scout/audible_fetch.py (22939b), audible_goodreads_deal_scout/audible_source.py (11091b), audible_goodreads_deal_scout/cli_errors.py (878b), audible_goodreads_deal_scout/constants.py (2362b), audible_goodreads_deal_scout/core.py (45254b), audible_goodreads_deal_scout/delivery.py (29981b), audible_goodreads_deal_scout/diagnostics.py (15245b), audible_goodreads_deal_scout/fit_evidence.py (7285b), audible_goodreads_deal_scout/goodreads_csv.py (6509b), audible_goodreads_deal_scout/goodreads_rating.py (6451b), audible_goodreads_deal_scout/html_extract.py (3391b), audible_goodreads_deal_scout/public_cli.py (39079b), audible_goodreads_deal_scout/rendering.py (8792b), audible_goodreads_deal_scout/repo_audit.py (2990b), audible_goodreads_deal_scout/runtime_contract.py (17485b), audible_goodreads_deal_scout/settings.py (6010b), audible_goodreads_deal_scout/shared.py (7889b), audible_goodreads_deal_scout/want_to_read_scan.py (34518b), CHANGELOG.md (10534b), config.example.json (618b), examples/preferences.example.md (644b), LICENSE.txt (1073b), README.md (31586b), scripts/audible-goodreads-deal-scout.sh (541b), skill-card.md (3088b), SKILL.md (17345b), TRUST.md (5373b), _meta.json (148b)\n\nFile v0.1.18:SKILL.md\n\n---\nname: audible-goodreads-deal-scout\ndescription: Evaluate an Audible daily promotion against Goodreads public score, optional Goodreads CSV shelves, optional freeform reading notes, optional delivery rules, and manual Want-to-Read discount scans. Use for first-run setup, deal checks, scheduled sends, and on-demand Goodreads backlog audits.\nlicense: MIT-0\nmetadata: {\"openclaw\":{\"emoji\":\"🎧\",\"skillKey\":\"audible-goodreads-deal-scout\",\"homepage\":\"https://github.com/lenpr/audible-goodreads-deal-scout\",\"category\":\"media\",\"requires\":{\"bins\":[\"sh\"],\"anyBins\":[\"python3\",\"python\"]}}}\n---\n\n# Audible Goodreads Deal Scout\n\nNever miss an Audible deal for a book you actually want to read.\n\nAudible Goodreads Deal Scout is a **ClawHub / OpenClaw skill** that checks Audible promotions against Goodreads ratings, your Goodreads shelves, and optional reading-taste notes. It is built for people who want fewer random deal notifications and more \"this is actually relevant to me\" recommendations.\n\nThe goal is not to buy more audiobooks. The goal is to notice the few Audible deals that match books you already care about.\n\n## What It Does\n\nUse this skill to:\n- check today's Audible daily deal and get a short recommendation\n- see whether the deal is already on your Goodreads Want-to-Read shelf\n- suppress books you already marked as read or currently reading\n- scan your Goodreads Want-to-Read shelf for Audible titles with visible discounts\n- rank discounted Want-to-Read matches by deal strength and Goodreads signal\n- create personalized recommendations from your Goodreads shelves, ratings, reviews, and taste notes\n- explain why a book may or may not fit your reading preferences, instead of only showing a generic score\n- optionally check member-visible Audible cash prices with a local Audible auth token\n- optionally deliver good matches to Telegram or another configured OpenClaw channel\n\nIf you do not want personalization, the skill still works with public Goodreads ratings only.\n\nThis skill reports opportunities only. It does not buy, reserve, check out, redeem credits, manage subscriptions, or complete purchases.\n\n## Getting The Most Value\n\nThe best setup uses:\n1. A Goodreads library CSV from the official Goodreads `Import and Export` page.\n2. Short taste notes about books, authors, genres, pacing, and themes you like or avoid.\n3. Optional Audible authentication when you want member-visible cash prices in Want-to-Read scans.\n\nWith those pieces, the skill can track today's Audible promotion, compare it against your Goodreads library, explain personal fit, and scan your Want-to-Read shelf for Audible titles that look discounted or priced below list.\n\n## Trust And Data Access\n\nThe skill reads only the files and services needed for its configured workflow.\n\n| Data or service | When used | Purpose |\n| --- | --- | --- |\n| Config file | Setup, daily checks, scans, delivery | Stores marketplace, thresholds, paths, privacy mode, and optional delivery settings |\n| Goodreads CSV | Only when configured | Detects `read`, `currently-reading`, and `to-read` shelves and uses ratings/reviews for fit |\n| Taste notes | Only when configured | Adds personal reading preferences for fit explanations |\n| Audible pages | Deal checks and Want-to-Read scans | Fetches daily promotions, search results, product pages, and visible pricing signals |\n| Audible auth file | Optional, explicit authenticated scans only | Checks member-visible cash prices for matched Audible titles through allowlisted token-refresh and Audible product-pricing API calls |\n| Goodreads public pages | Runtime lookup and optional rating enrichment | Resolves public rating evidence and fills missing Want-to-Read average ratings |\n| OpenClaw CLI | Optional delivery, cron, and diagnostics | Sends configured messages, registers requested cron jobs, and checks local readiness |\n\nThe local auth file is sensitive. Do not paste its contents into chat, commit it, or publish it. The auth flow requests cookie-style Audible/Amazon credential types for compatibility because anonymous pages may hide member cash prices, but the skill persists only the bearer access/refresh token fields it uses for token refresh and Audible product-price lookup.\n\nThe bundled runtime requires Python 3.11 or newer. Invoke the wrapper with `sh` so the skill remains usable when an installer does not preserve executable bits.\n\nFor a fuller trust and data-access summary, see `TRUST.md` in the published bundle or repository.\n\n## Optional Audible Authentication\n\nAudible authentication is optional and separate from the normal daily-deal workflow. The skill works without it, but anonymous Audible pages often hide cash prices behind credit or membership UI.\n\nUse authenticated price lookup only when the user explicitly wants member-visible cash prices in Want-to-Read scans. Do not ask for the user's Audible or Amazon password. Use `audible-auth-start`, `audible-auth-finish`, and `audible-auth-status` instead. Never read or display the auth file contents; status commands intentionally report readiness, expiry, permissions, and allowed-use metadata without token values.\n\n## Agent Runtime Instructions\n\nUse this skill when the user wants to:\n- set up a reusable Audible deal workflow\n- check the current Audible daily promotion\n- scan Goodreads Want-to-Read books for visible Audible US discounts\n- personalize the result with a Goodreads CSV and/or freeform notes\n- finalize and optionally deliver the result into a configured channel\n\n## Runtime output contract\n\nThe skill runtime must return JSON only in this shape:\n\n```json\n{\n  \"schemaVersion\": 1,\n  \"goodreads\": {\n    \"status\": \"resolved | no_match | lookup_failed\",\n    \"url\": \"string | null\",\n    \"title\": \"string | null\",\n    \"author\": \"string | null\",\n    \"averageRating\": \"number | null\",\n    \"ratingsCount\": \"integer | null\",\n    \"evidence\": \"string | null\"\n  },\n  \"fit\": {\n    \"status\": \"written | not_applicable | unavailable\",\n    \"sentence\": \"string | null\"\n  }\n}\n```\n\n## Use the Python prep layer first\n\nDo not fetch Audible yourself in model text. Always start with the prep layer:\n\n```bash\nsh \"{baseDir}/scripts/audible-goodreads-deal-scout.sh\" prepare --config-path \"<config-path>\" --invocation-mode manual\n```\n\nBy default, `prepare` uses `audibleFetchBackend: auto`: guard the URL against non-Audible destinations, try Python fetch first, then use browser-like `curl` fallback for recoverable Audible HTTP failures such as Python-client `503` rejections. Use `--audible-fetch-backend python` or `--audible-fetch-backend curl` only for explicit diagnostics.\n\nPrep returns JSON with:\n- `status: ready | suppress | error`\n- `reasonCode`\n- `warnings[]`\n- `audible`\n- `personalData`\n- `artifacts`\n- `metadata`, including `metadata.fetch` when fetch diagnostics are available\n\nIf prep returns `suppress` or `error`, surface that result directly and stop. Do not do Goodreads lookup or fit writing after a prep-layer short-circuit.\n\n## Setup\n\nIf the skill is not configured yet, gather:\n1. Audible store\n2. Whether the user wants personalization\n3. Optional Goodreads CSV path\n4. Optional notes file or pasted notes\n5. Optional threshold override from the default `3.8`\n6. Optional delivery channel and target\n7. Delivery policy: `positive_only`, `always_full`, or `summary_on_non_match`\n8. Whether daily automation should be enabled\n\nThen write config through:\n\n- If the user does not request a custom path, use the default workspace-root storage path: `<workspace>/.audible-goodreads-deal-scout/`.\n- Do not invent legacy names like `.audible-goodreads-deal`.\n- Do not store mutable config, state, or artifacts inside `{baseDir}` or the installed skill folder. `openclaw skills install` and `openclaw skills update --force` replace the workspace skill directory.\n- Treat relative paths stored in config as relative to the config file's directory. CLI arguments are relative to the current shell directory.\n\n```bash\nsh \"{baseDir}/scripts/audible-goodreads-deal-scout.sh\" setup \\\n  --config-path \"<config-path>\" \\\n  --audible-marketplace \"<marketplace>\" \\\n  --threshold \"<threshold>\" \\\n  [--goodreads-csv \"<csv-path>\"] \\\n  [--notes-file \"<notes-file>\"] \\\n  [--notes-text \"<inline notes>\"] \\\n  [--delivery-channel \"telegram\"] \\\n  [--delivery-target \"<target>\"] \\\n  [--delivery-policy \"positive_only\"] \\\n  [--daily-automation | --no-daily-automation] \\\n  [--no-delivery] \\\n  [--register-cron]\n```\n\nUse interactive `setup` only when the user explicitly wants prompt-by-prompt CLI onboarding. Otherwise prefer the non-interactive command with concrete flags.\n\nBefore enabling daily automation, make sure the user's OpenClaw host can run the exact scheduled exec command unattended. Cron runs cannot wait for command approval. Registered jobs use an OpenClaw condition trigger; enable `cron.triggers.enabled` only on a trusted host where the user controls every cron-authoring agent and the local skill files. The job uses the marketplace's IANA timezone, lightweight bootstrap context, and disabled model thinking.\n\nTo remove automation, rerun non-interactive setup with `--no-daily-automation --register-cron`; this disables the related job and clears its trigger and fallback route. Use `--no-delivery` to clear the configured channel and target while preserving unrelated config.\n\n## Want-to-Read discount scan\n\nUse this only when the user asks to scan Goodreads Want-to-Read books for Audible discounts. This is a manual audit command, not a cron or delivery workflow.\n\nRequirements:\n- The configured Goodreads CSV must exist.\n- V1 supports Audible US only.\n- Do not create cron jobs or send delivery messages for this command.\n- Do not perform extra model web searches; the Python command handles Audible lookup and report generation.\n- If setup or runtime state is unclear, run `doctor` before retrying.\n\nRun:\n\n```bash\nsh \"{baseDir}/scripts/audible-goodreads-deal-scout.sh\" scan-want-to-read \\\n  --config-path \"<config-path>\" \\\n  [--audible-auth-path \"<auth-path>\"] \\\n  [--limit 40] \\\n  [--offset 0] \\\n  [--scan-order newest] \\\n  [--progress plain] \\\n  [--no-goodreads-rating-enrichment] \\\n  [--goodreads-rating-limit 20] \\\n  [--output-json \"<json-path>\"] \\\n  [--output-md \"<markdown-path>\"]\n```\n\nDefault behavior:\n- Print compact Markdown to stdout.\n- Write progress to stderr by default. Use `--progress json` for machine-readable JSONL progress or `--progress none` when silence is required.\n- Show visible numeric discounts first.\n- Suppress long non-deal lists unless `--include-non-deals` is requested.\n- Suppress duplicate Audible product matches in the final report while preserving scanned-row counts.\n- Use `--offset` and `--limit` for large Goodreads backlogs.\n- For long agent-run scans, prefer `--progress json` plus `--output-json` and `--output-md` so progress logs and final reports stay separate.\n- Use `pricing.priceBasis` and `pricing.dealType` to distinguish member cash prices below list from true limited-time sale or promotion signals.\n- If CSV average ratings are missing, the command may enrich a small number of discounted rows from public Goodreads book pages by Goodreads book id. Disable with `--no-goodreads-rating-enrichment` when the user wants no Goodreads page fetches.\n\nImportant caveat: Audible often hides cash prices behind credit or membership UI. Treat `price_hidden`, `price_unknown`, and `needs_review` as honest uncertainty, not as failures.\n\nOptional authenticated pricing:\n- If the user asks for headless authenticated Audible prices, use `audible-auth-start` and `audible-auth-finish`.\n- Do not ask for the user's Audible or Amazon password.\n- Store the auth file under the workspace storage directory, for example `<workspace>/.audible-goodreads-deal-scout/audible-auth.json`.\n- Treat the auth file as sensitive and never paste its token contents into chat.\n- Authenticated lookup is code-restricted to validated 10-character Audible product ids, token refresh, and allowlisted Audible/Amazon API domains.\n- Authenticated scans usually spend one search request plus one authenticated price request for each matched title; set `--max-requests` accordingly.\n- Treat cash pricing fields as the source of truth and do not classify Audible credit prices, including `credit_price`, as cash discounts.\n- Treat authenticated `discounted` as \"member-visible cash price below list price\", not proof of a limited-time sale; check `pricing.dealType`.\n- Use `audible-auth-status` to check readiness, expiry, and file permissions without exposing tokens.\n\n```bash\nsh \"{baseDir}/scripts/audible-goodreads-deal-scout.sh\" audible-auth-start \\\n  --auth-path \"<workspace>/.audible-goodreads-deal-scout/audible-auth.json\" \\\n  --audible-marketplace us\n\nsh \"{baseDir}/scripts/audible-goodreads-deal-scout.sh\" audible-auth-finish \\\n  --auth-path \"<workspace>/.audible-goodreads-deal-scout/audible-auth.json\" \\\n  --redirect-url \"<final-amazon-redirect-url>\"\n```\n\nTroubleshooting:\n\n```bash\nsh \"{baseDir}/scripts/audible-goodreads-deal-scout.sh\" doctor \\\n  --config-path \"<config-path>\"\n\nsh \"{baseDir}/scripts/audible-goodreads-deal-scout.sh\" audible-auth-status \\\n  --auth-path \"<workspace>/.audible-goodreads-deal-scout/audible-auth.json\"\n```\n\nTo verify the installed bundle version:\n\n```bash\nsh \"{baseDir}/scripts/audible-goodreads-deal-scout.sh\" version\n```\n\nUse `doctor --check-audible-fetch` only when the user wants a live host probe of the Audible daily-deal fetch path.\n\n## Ready flow\n\nFor `ready_*` prep results:\n1. Read `artifacts.runtimePromptPath`\n2. Read `artifacts.runtimeInputPath`\n3. Resolve the Goodreads public book page and score with OpenClaw web/search\n4. Produce JSON only that matches `artifacts.runtimeOutputSchemaPath`\n5. Finalize through:\n\n```bash\nsh \"{baseDir}/scripts/audible-goodreads-deal-scout.sh\" finalize \\\n  --prepare-json \"<prepare-result-path>\" \\\n  --runtime-output \"<runtime-output-path>\"\n```\n\nIf the user wants the result routed to a configured channel:\n\n```bash\nsh \"{baseDir}/scripts/audible-goodreads-deal-scout.sh\" run-and-deliver \\\n  --config-path \"<config-path>\" \\\n  --prepare-json \"<prepare-result-path>\" \\\n  --runtime-output \"<runtime-output-path>\"\n```\n\n## Decision rules\n\n- If `personalData.exactShelfMatch == \"to-read\"`, recommend immediately. This overrides the Goodreads threshold.\n- If prep already marked the book as `read` or `currently-reading`, do not continue.\n- Otherwise enforce the Goodreads threshold from `metadata.threshold`.\n- If Goodreads lookup fails, use `error_goodreads_lookup_failed`.\n- If Goodreads cannot confirm a matching book page, use `suppress_no_goodreads_match`.\n\nSkill-layer reason codes:\n- `recommend_to_read_override`\n- `recommend_public_threshold`\n- `suppress_below_goodreads_threshold`\n- `suppress_no_goodreads_match`\n- `error_goodreads_lookup_failed`\n\n## Fit writing\n\nThe model writes the fit paragraph. Python does not call a provider API directly.\n\nUse:\n- Goodreads public score\n- `artifacts.fitEvidencePath` as the primary candidate-specific taste evidence when present\n- `artifacts.fitContextPath`\n- `artifacts.reviewSourcePath` when present\n- `artifacts.notesPath` when present\n\nRules:\n- Do not drop rated/reviewed CSV rows for prompt convenience.\n- Start with the bounded fit-evidence artifact and consult the complete fit context only when the selected evidence is insufficient or contradictory.\n- Do not infer why the user liked or disliked a title from a rating alone; use written reviews or notes for preference claims.\n- Summarize each written Goodreads review to 500 characters or fewer before using it as evidence.\n- If `personalData.privacyMode == \"minimal\"`, do not use personal CSV or notes content in the fit paragraph.\n- If no meaningful personal data exists, say so explicitly instead of inventing taste evidence.\n\nFallback lines:\n- `Fit: No personal preference data was configured, so this recommendation is based only on the public Goodreads score.`\n- `Fit: Personalized fit feedback is unavailable right now, but the recommendation decision still completed.`\n\n## Delivery\n\n`run-and-deliver` must respect the configured `deliveryPolicy`:\n- `positive_only`: deliver only `recommend`\n- `always_full`: deliver the full card for every final status\n- `summary_on_non_match`: deliver full `recommend`, but a short summary card for `suppress` or `error`\n\nRegistered scheduled runs invoke `scheduled-gate` from a deterministic condition trigger. Do not run `prepare` again when the trigger appends preprepared instructions. A `fire: false` result is complete and must stay silent. For `fire: true`, follow the appended artifact paths and commands exactly, write valid runtime JSON, and call `mark-emitted` only when `run-and-deliver` reports `delivered: true`.\n\nFor a manually orchestrated scheduled run, prep with `--invocation-mode scheduled`. If prep returns `suppress_duplicate_scheduled_run`, stop quietly. After a delivered scheduled result, mark the deal as emitted with:\n\n```bash\nsh \"{baseDir}/scripts/audible-goodreads-deal-scout.sh\" mark-emitted \\\n  --state-file \"<state-file>\" \\\n  --prepare-json \"<prepare-result-path>\" \\\n  --deal-key \"<deal-key>\"\n```\n\nUse the same current scheduled prepare artifact that was delivered. `run-and-deliver` refuses scheduled error prep results and stale scheduled artifacts whose `metadata.storeLocalDate` is not the current Audible marketplace date.\n\nFile v0.1.18:README.md\n\n# Audible Goodreads Deal Scout\n\nNever miss an Audible deal for a book you actually want to read.\n\nAudible Goodreads Deal Scout is a **ClawHub / OpenClaw skill** that checks Audible promotions against Goodreads ratings, your Goodreads shelves, and optional reading-taste notes. It is built for people who want fewer random deal notifications and more \"this is actually relevant to me\" recommendations.\n\nThe goal is not to buy more audiobooks. The goal is to notice the few Audible deals that match books you already care about.\n\nThe skill reports opportunities only. It does not buy, reserve, check out, redeem credits, manage subscriptions, or complete purchases.\n\nFor a concise security and data-access summary, see [TRUST.md](TRUST.md).\n\n## Use This Skill To\n\nUse this skill to:\n\n- Check today's Audible daily deal and get a short recommendation.\n- See whether the deal is already on your Goodreads Want-to-Read shelf.\n- Suppress books you already marked as read or currently reading.\n- Scan your Goodreads Want-to-Read shelf for Audible titles with visible discounts.\n- Rank discounted Want-to-Read matches by deal strength and Goodreads signal.\n- Create highly personalized recommendations from your Goodreads shelves, ratings, reviews, and taste notes.\n- Explain why a book may or may not fit your reading preferences, instead of only showing a generic score.\n- Optionally check member-visible Audible cash prices with a local Audible auth token.\n- Optionally deliver good matches to Telegram or another configured OpenClaw channel.\n\nIf you do not want personalization, the skill still works with public Goodreads ratings only.\n\n## How To Get The Most Value\n\nThe skill works with public data only, but it gets much better when you give it a little personal context.\n\nThe best setup is:\n\n1. Export your Goodreads library CSV.\n   Use the official Goodreads library exporter from Goodreads' `Import and Export` page. This lets the skill know what you already read, what you are currently reading, and what is on your Want-to-Read shelf.\n2. Add short taste notes.\n   A few paragraphs are enough. You can write them yourself, dictate them quickly, or ask an AI to draft taste notes from your favorite books, disliked books, preferred genres, and reading habits. These notes help the skill explain whether a deal actually fits you, not just whether it is popular.\n3. Optionally add Audible authentication for member prices.\n   Anonymous Audible pages often hide cash prices or show credit-based buying options. If you provide a local Audible auth token, the skill can check member-visible cash prices for matched titles and produce a more useful Want-to-Read discount report.\n\nWith all three pieces, the skill can help keep track of:\n\n- today's Audible promotion\n- whether the book is already in your Goodreads library\n- whether it is on your Want-to-Read shelf\n- whether it looks like a good fit for your taste\n- which Want-to-Read books are available on Audible\n- which matched titles appear discounted or priced below list\n- which deals are worth looking at first\n\nIf you are looking at this repository on GitHub, you are looking at the **source for a publishable ClawHub skill**, not a generic Python app or a standalone website.\n\nIf you want to re-implement the workflow without using the shipped skill directly, see [PROMPT_REQUEST.md](PROMPT_REQUEST.md). It captures the intention, scope, design guardrails, edge cases, and example prompt in one place.\n\n## Install or publish\n\nIf you just want to use it in OpenClaw once it is published:\n\n```bash\nopenclaw skills install audible-goodreads-deal-scout\n```\n\nStart a new OpenClaw session after install or after changing skill config so the fresh skill snapshot is picked up cleanly.\n\nIf you want to publish your own version from this repo:\n\n```bash\nclawhub login\nclawhub publish . \\\n  --slug audible-goodreads-deal-scout \\\n  --name \"Audible Goodreads Deal Scout\" \\\n  --version 0.1.18 \\\n  --changelog \"Harden scheduled execution, auth, config, scans, and release validation.\" \\\n  --tags latest\n```\n\nThe runtime requires Python 3.11 or newer and `sh`. `curl` is optional but recommended as a fallback when Audible rejects the built-in HTTP client.\n\n## 5-minute setup\n\nIf you want one straightforward setup path, use this:\n\n1. Pick your Audible store. If you do nothing, it defaults to `us`.\n2. Export your Goodreads library CSV if you want personalization.\n3. Optionally create a short notes file with what you like and dislike.\n4. Run:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh setup\n```\n\nThe setup response includes `nextSteps` with ready-to-run commands for `doctor`, checking the daily deal, scanning Want-to-Read books when a CSV is configured, and optional Audible auth.\n\nBy default, the skill writes its config, state, and artifacts under `.audible-goodreads-deal-scout/` in the active OpenClaw workspace.\n\nThat storage lives in the workspace, not inside `skills/audible-goodreads-deal-scout/`, because `openclaw skills install` and `openclaw skills update --force` can replace the installed skill folder.\n\nOnly point `goodreadsCsvPath`, `notesFile`, `configPath`, and `stateFile` at files or directories you actually want this skill to read or write.\n\nRelative paths inside the JSON config are resolved from the directory containing that config file. CLI path arguments remain relative to the shell's current directory.\n\n5. Then evaluate the current deal:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh prepare \\\n  --config-path .audible-goodreads-deal-scout/config.json\n```\n\n## How to get your Goodreads CSV\n\nIf you use Goodreads, the skill gets much stronger when you export your library.\n\nThe usual path is:\n1. Open `My Books`\n2. Open `Import and Export`\n3. Choose `Export Library`\n4. Wait for Goodreads to generate the file\n5. Download the CSV and point the skill at it with `goodreadsCsvPath`\n\nWhy the CSV matters:\n- it tells the skill what you already marked as `read`\n- it tells the skill what is already on your `to-read` shelf\n- it gives the fit step access to your ratings and written reviews\n\nIf your export is old, the skill will warn you, but it can still run.\n\n## If you do not use Goodreads\n\nThat is still a valid setup.\n\nYou can use a notes-only workflow:\n- no Goodreads CSV\n- one strong text file about your taste\n\nThe better the notes, the better the fit paragraph.\n\nGood notes usually include:\n- 5 to 15 books or authors you genuinely liked\n- a few examples of books you disliked and why\n- genres you seek out\n- genres you avoid\n- pacing preferences\n- tone preferences\n- what feels too sentimental, too slow, too commercial, too dark, too clever, too flat, and so on\n\nA strong notes file sounds like you talking to a smart bookseller, not like metadata.\n\nUseful:\n\n```md\nI like morally serious fiction, political tension, and books with ideas.\nI often like Orwell, Ishiguro, Le Guin, Vonnegut, and literary sci-fi.\nI lose interest when a book gets too sentimental or too plot-mechanical.\nI like books that are sharp, unsparing, and a bit strange, but still readable.\n```\n\nToo weak:\n\n```md\nI like good books.\n```\n\nIf you do not have Goodreads, the best setup is:\n- a thoughtful notes file\n- the default public Goodreads check\n- `deliveryPolicy: positive_only`\n\n## How the recommendation works\n\nAt a high level:\n- the skill fetches the current Audible daily promotion\n- it resolves the matching Goodreads page and public rating\n- it applies your Goodreads shelf rules if you provided a CSV\n- it uses your notes and/or Goodreads history to shape the fit paragraph\n- it decides whether to deliver the result based on your delivery policy\n\n### The default Goodreads threshold\n\nThe default threshold is `3.8`.\n\nThat means:\n- a public Goodreads average rating of `3.80` or lower is treated as below your quality cutoff\n- a rating above `3.8` is eligible\n\nThis is the **public Goodreads average**, not your own rating.\n\nGood starting points:\n- `4.0` if you want to be stricter\n- `3.8` if you want a balanced default\n- `3.6` or `3.7` if you want more titles to pass through\n\n### Goodreads shelf rules\n\nIf you provide a Goodreads CSV:\n- `read` => suppress\n- `currently-reading` => suppress\n- `to-read` => recommend immediately\n\nThat `to-read` override is intentional. If you already saved the book for later, that is treated as a strong positive signal and it can override the public Goodreads threshold.\n\n## Scan your Want-to-Read shelf for Audible discounts\n\nIf you configured a Goodreads CSV, you can also run a manual audit of books on your Goodreads `to-read` shelf:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh scan-want-to-read \\\n  --config-path .audible-goodreads-deal-scout/config.json \\\n  --limit 40 \\\n  --offset 0 \\\n  --progress plain\n```\n\nThis is intentionally an on-demand scan, not a scheduled monitor. It helps answer: \"Which books I already want to read appear to have a visible Audible discount right now?\"\n\nDefault behavior:\n- scans Audible US only in this first version\n- reads the current Goodreads CSV fresh each run\n- searches the first Audible result page for each selected Goodreads book\n- inspects the first three Audible result cards\n- fetches a product page only when the search card already shows plausible numeric discount evidence\n- prints compact Markdown to stdout\n- writes scan progress to stderr by default, so long runs can be monitored without corrupting Markdown/JSON output\n- keeps non-deals out of the default Markdown so the useful deals stay visible\n- suppresses duplicate Audible product matches in the final report while preserving scanned-row counts\n\nUseful batching pattern for larger shelves:\n\n```bash\n# Day 1\nsh ./scripts/audible-goodreads-deal-scout.sh scan-want-to-read \\\n  --config-path .audible-goodreads-deal-scout/config.json \\\n  --scan-order newest \\\n  --limit 40 \\\n  --offset 0\n\n# Day 2\nsh ./scripts/audible-goodreads-deal-scout.sh scan-want-to-read \\\n  --config-path .audible-goodreads-deal-scout/config.json \\\n  --scan-order newest \\\n  --limit 40 \\\n  --offset 40\n```\n\nUseful output flags:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh scan-want-to-read \\\n  --config-path .audible-goodreads-deal-scout/config.json \\\n  --output-json .audible-goodreads-deal-scout/reports/want-to-read.json \\\n  --output-md .audible-goodreads-deal-scout/reports/want-to-read.md \\\n  --include-non-deals\n```\n\nThe scan is deliberately conservative. If Audible hides cash pricing behind credits, membership language, or extra buying-choice UI, the result is marked as hidden or unknown instead of guessing. If a title or author match is ambiguous, it is marked for review instead of being treated as a deal.\n\nThe Markdown report shows whether authenticated pricing was enabled, live request usage, cache hits/writes, and a suggested next `--offset` command when more selected Want-to-Read books remain.\n\nPricing fields now separate two ideas:\n- `priceBasis` says where the price came from, for example `audible_public_cash` or `audible_member_cash`.\n- `dealType` says what kind of opportunity it appears to be, for example `limited_time_sale`, `member_cash_below_list`, or `cash_price_below_list`.\n\nGoodreads ratings:\n- If your Goodreads CSV includes an average-rating column, the scan uses it for ranking.\n- If the CSV does not include that column, the scan can enrich up to 20 discounted results from public Goodreads book pages when the CSV has Goodreads book ids.\n- Use `--no-goodreads-rating-enrichment` if you want to avoid those public Goodreads rating lookups.\n- Use `--goodreads-rating-limit N` to adjust the enrichment cap.\n\nProgress output:\n- `--progress plain` writes human-readable progress lines to stderr. This is the default CLI behavior.\n- `--progress json` writes JSONL progress events to stderr for agents and log processors.\n- `--progress none` disables progress output.\n- `--progress-interval 5` controls the minimum seconds between item progress updates. Start, stop, and completion events are always emitted when progress is enabled.\n\nFor long OpenClaw-agent runs, prefer `--progress json` plus `--output-json` and `--output-md`. Progress goes to stderr, while the report files stay stable and can be read after the command finishes or stops early.\n\n### Optional authenticated Audible price lookup\n\nAnonymous Audible pages often hide cash prices. If you want the Want-to-Read scan to check member-visible pricing on a headless OpenClaw machine, you can create a local Audible auth file through an external-browser flow.\n\nThis does **not** put your Audible password in the skill config. The flow prints an Amazon login URL, you open it on another device, complete login there, and paste the final redirect URL back into the CLI.\n\nThe resulting auth file is powerful local state: the flow requests cookie-style Audible/Amazon credential types for compatibility, then persists the bearer access/refresh token fields needed for token refresh and member-visible product-price lookup. The skill confines authenticated use to token refresh plus validated Audible product-price lookups on allowlisted API hosts, and `audible-auth-status` reports readiness without printing token contents.\n\nStart auth:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh audible-auth-start \\\n  --auth-path .audible-goodreads-deal-scout/audible-auth.json \\\n  --audible-marketplace us\n```\n\nOpen the printed `loginUrl` in your own browser. After login, Amazon will land on an error or not-found page; copy that final address-bar URL and finish auth:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh audible-auth-finish \\\n  --auth-path .audible-goodreads-deal-scout/audible-auth.json \\\n  --redirect-url \"<final-amazon-redirect-url>\"\n```\n\nThen scan with authenticated price lookup:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh scan-want-to-read \\\n  --config-path .audible-goodreads-deal-scout/config.json \\\n  --audible-auth-path .audible-goodreads-deal-scout/audible-auth.json \\\n  --limit 40 \\\n  --max-requests 90\n```\n\nYou can also save the auth path in `config.json` as `audibleAuthPath`, or set it during scripted setup with `--audible-auth-path`.\n\nAuthenticated scans usually spend one search request plus one authenticated price request for each matched Audible title. Use a higher `--max-requests` value than you would for anonymous scans. The authenticated price parser treats cash prices as the source of truth and ignores Audible credit prices such as `credit_price`.\n\nAuthenticated `discounted` means Audible returned a member-visible cash price below its list price for the product. It does not always prove a limited-time sale; check `dealType` in JSON if you need to distinguish `member_cash_below_list` from `limited_time_sale`.\n\nYou can test one known Audible ASIN first:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh audible-auth-test-price \\\n  --auth-path .audible-goodreads-deal-scout/audible-auth.json \\\n  --asin B08V8B2CGV\n```\n\nThe test response should include `pricingStatus`, `currentPrice`, `listPrice`, and `discountPercent` when Audible returns visible member cash pricing for that ASIN.\n\nCheck auth readiness and file permissions without printing tokens:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh audible-auth-status \\\n  --auth-path .audible-goodreads-deal-scout/audible-auth.json\n```\n\nIf the status reports broad file permissions on a local POSIX host, tighten them with:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh audible-auth-status \\\n  --auth-path .audible-goodreads-deal-scout/audible-auth.json \\\n  --fix-permissions\n```\n\nThe auth file is sensitive. Keep it under `.audible-goodreads-deal-scout/` in your OpenClaw workspace, do not commit it, do not paste it into chat, and remove it if you no longer want the skill to have authenticated Audible API access.\n\n## Supported marketplaces\n\nSupported and fixture-tested marketplace keys:\n- `us`\n- `uk`\n- `de`\n- `ca`\n- `au`\n\nIf you do nothing, the default is `us`.\n\nSupport here means the repo has fixture-backed coverage for:\n- daily-promotion detection\n- promotional price extraction\n- book identity extraction\n\nLive marketplace behavior can still vary. A supported store may still return:\n- no active promotion\n- a blocked page\n- a page-layout drift error\n\nDaily-promotion fetches use `audibleFetchBackend: \"auto\"` by default. That means the skill tries the built-in Python fetch path first and falls back to browser-like `curl` when Audible rejects the Python client with recoverable HTTP failures such as `503`. Use `\"python\"` or `\"curl\"` only when you deliberately want to force one backend.\n\nThe Want-to-Read discount scan is currently US-only. The daily-promotion workflow remains fixture-tested for the marketplace keys listed above.\n\nIf you want a non-US store, set `audibleMarketplace` to one of the keys above:\n\n```json\n{\n  \"audibleMarketplace\": \"uk\",\n  \"audibleFetchBackend\": \"auto\"\n}\n```\n\n## Privacy and data use\n\nThis part should be explicit.\n\n- The Python prep layer reads your Goodreads CSV locally.\n- The Python prep layer also reads your notes file locally.\n- The skill will read whatever file paths you configure, so keep those paths limited to the files you intend it to use.\n- The model step starts with a bounded, candidate-specific fit-evidence file selected from your ratings and reviews. The complete fit context remains available only as fallback evidence.\n- Rating-only entries establish that you liked or disliked a title, but the runtime prompt uses reviews or preference notes before claiming why.\n- In `privacyMode: \"minimal\"`, the skill still uses local shelf logic, but it does **not** pass your personal CSV or notes content into the model fit step.\n- Delivery targets are whatever you configure in your own OpenClaw runtime.\n\nIf you want the safest default for personal data sharing, use:\n\n```json\n{\n  \"privacyMode\": \"minimal\"\n}\n```\n\n## What a notes file should look like\n\nIt does **not** need strict structure. A short, honest, messy note is fine.\n\nExample file: `examples/preferences.example.md`\n\nGood notes usually include:\n- books or authors you reliably like\n- genres or tones you usually avoid\n- pacing preferences\n- whether you like literary, commercial, cerebral, emotional, satirical, dark, warm, and so on\n\nWeak notes are still accepted, but they produce weaker fit output. For example, `I like good books` is valid input, but not very useful evidence.\n\n## Delivery policies\n\n`deliveryPolicy` controls how noisy the skill is:\n\n| Policy | Best for | Behavior |\n| --- | --- | --- |\n| `positive_only` | most people | send only likely fits |\n| `summary_on_non_match` | people who want visibility into skips | send full recommendations, but short summary cards for suppressions/errors |\n| `always_full` | logging and audits | send every final result in full |\n\nRecommended default:\n- `positive_only`\n\nThat gives the best signal-to-noise ratio for most users.\n\n## Daily automation\n\nRegister the marketplace-aware daily schedule explicitly:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh setup \\\n  --non-interactive \\\n  --config-path .audible-goodreads-deal-scout/config.json \\\n  --daily-automation \\\n  --daily-cron \"15 1 * * *\" \\\n  --register-cron\n```\n\nThe job uses the marketplace's IANA timezone, such as `America/Los_Angeles` for Audible US, so daylight-saving changes do not shift the intended local run time. Setup reconciles an existing related job instead of creating duplicates.\n\nScheduled runs first execute a deterministic condition trigger. Duplicate runs and deterministic suppressions under `positive_only` return `fire: false`, so OpenClaw does not start a model or create run history. Runs that need Goodreads lookup or personalized writing use lightweight bootstrap context with model thinking disabled, then follow the generated runtime prompt.\n\nCondition triggers are unattended code execution. Enable `cron.triggers.enabled` only on a trusted OpenClaw host whose cron-authoring agents and local skill files you control. Scheduled shell commands also need a non-interactive exec approval policy.\n\n```bash\nopenclaw config set cron.triggers.enabled true --strict-json\n```\n\nDisable an existing related job and clear its trigger and delivery route with:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh setup \\\n  --non-interactive \\\n  --config-path .audible-goodreads-deal-scout/config.json \\\n  --no-daily-automation \\\n  --register-cron\n```\n\nUse `--no-delivery` during setup to clear a configured channel and target without changing unrelated settings.\n\n## Telegram, WhatsApp, and other channels\n\nThis repository does **not** ship its own Telegram or WhatsApp connector.\n\nInstead, it uses the OpenClaw message surface:\n- `openclaw message send --channel ... --target ...`\n\nThat means delivery works whenever your OpenClaw environment already has a supported channel configured.\n\n### Telegram\n\nIf your OpenClaw setup supports Telegram delivery, configure:\n\n```json\n{\n  \"deliveryChannel\": \"telegram\",\n  \"deliveryTarget\": \"-1000000000000\"\n}\n```\n\n`deliveryTarget` is the Telegram chat or channel id you want to post into.\n\n### WhatsApp\n\nWhatsApp can work **only if** your OpenClaw install already exposes a WhatsApp-capable message channel.\n\nIn that case the pattern is the same:\n\n```json\n{\n  \"deliveryChannel\": \"whatsapp\",\n  \"deliveryTarget\": \"<your-whatsapp-target>\"\n}\n```\n\nThis repo does not create that WhatsApp channel. It only uses it if your OpenClaw runtime already provides it.\n\n## What the output looks like\n\n### Positive recommendation\n\n```text\nAudible US Daily Promotion — 2026-04-20\n\n𝗦𝗹𝗮𝘂𝗴𝗵𝘁𝗲𝗿𝗵𝗼𝘂𝘀𝗲-𝗙𝗶𝘃𝗲 — Kurt Vonnegut (2015)\nPrice: $1.99 (-87%, list price $14.95)\nGoodreads rating: 4.11 (1,364,737 ratings)\nLength: 5:13 hrs\nGenre: Literature & Fiction, Thought-Provoking, Fiction, Witty\n\nSlaughterhouse-Five is the now famous parable of Billy Pilgrim...\n\nFit: Strong match, on your to-read shelf. You tend to respond well to fiction that is intellectually playful, structurally bold, and willing to smuggle serious ideas through wit. The main risk is that Vonnegut's emotional distance and satirical flatness may leave you admiring it more than fully feeling it.\n\nAudible: https://www.audible.com/pd/...\nGoodreads: https://www.goodreads.com/book/show/...\n```\n\n### Short non-match summary\n\n```text\nAudible US Daily Promotion — 2026-04-20\n\n𝗦𝗹𝗮𝘂𝗴𝗵𝘁𝗲𝗿𝗵𝗼𝘂𝘀𝗲-𝗙𝗶𝘃𝗲 — Kurt Vonnegut (2015)\n\nFit: You marked it as read on Goodreads.\n\nAudible: https://www.audible.com/pd/...\n```\n\n## One complete walkthrough\n\nIf you want to see the whole flow once from start to finish, this is the cleanest path.\n\n1. Write a config and optional notes/delivery settings:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh setup \\\n  --non-interactive \\\n  --config-path .audible-goodreads-deal-scout/config.json \\\n  --audible-marketplace us \\\n  --audible-auth-path .audible-goodreads-deal-scout/audible-auth.json \\\n  --threshold 3.8 \\\n  --goodreads-csv \"/absolute/path/to/goodreads_library_export.csv\" \\\n  --notes-file \"/absolute/path/to/preferences.md\" \\\n  --delivery-channel telegram \\\n  --delivery-target \"-1000000000000\" \\\n  --delivery-policy positive_only\n```\n\n2. Prepare today's deal:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh prepare \\\n  --config-path .audible-goodreads-deal-scout/config.json\n```\n\nThat always writes the current prep result to `.audible-goodreads-deal-scout/artifacts/current/prepare-result.json`, including error or suppress outcomes. Ready outcomes also include:\n- `runtime-input.json`\n- `runtime-prompt.md`\n- `runtime-output-schema.json`\n\n3. Let the OpenClaw runtime produce a `runtime-output.json` file that matches the schema from step 2. A typical successful output looks like:\n\n```json\n{\n  \"schemaVersion\": 1,\n  \"goodreads\": {\n    \"status\": \"resolved\",\n    \"url\": \"https://www.goodreads.com/book/show/1\",\n    \"title\": \"Signal Fire\",\n    \"author\": \"Jane Story\",\n    \"averageRating\": 4.15,\n    \"ratingsCount\": 9501\n  },\n  \"fit\": {\n    \"status\": \"written\",\n    \"sentence\": \"Fit: Likely to work if you want sharp, idea-driven speculative fiction. The main risk is that it may feel more cerebral than emotionally warm.\"\n  }\n}\n```\n\n4. Finalize the public result contract:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh finalize \\\n  --prepare-json .audible-goodreads-deal-scout/artifacts/current/prepare-result.json \\\n  --runtime-output /tmp/runtime-output.json\n```\n\n5. If you configured delivery, send the finished message:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh run-and-deliver \\\n  --config-path .audible-goodreads-deal-scout/config.json \\\n  --prepare-json .audible-goodreads-deal-scout/artifacts/current/prepare-result.json \\\n  --runtime-output /tmp/runtime-output.json\n```\n\nIf you just want to inspect the decision locally, stop after `finalize`.\n\n## Troubleshooting\n\nThree issues cause most confusing runs:\n\n- Wrong notes path: if `notesFile` or `preferencesPath` points at a missing file, the prep step now returns `error_missing_notes_file` instead of silently continuing.\n- Wrong CSV header override: `--csv-column role=Header` must match the Goodreads export header exactly. If you are unsure, run `show-csv-headers` first.\n- Stale Goodreads export: if the CSV is old, the skill can still run, but read status, shelf state, and fit evidence may lag behind your actual library.\n- Stale scheduled artifact: scheduled `run-and-deliver` refuses error prep results and stale `prepare-result.json` files whose `metadata.storeLocalDate` no longer matches the current Audible marketplace date.\n- Stale downstream artifacts: every fresh `prepare` removes old `runtime-output.json`, `run-and-deliver-result.json`, and `mark-emitted-result.json` from the current artifact directory before writing the new prep result.\n- Transient Audible daily-deal pages: the prep step retries transient fetch failures and temporary no-active-promotion parses before returning a suppression or error. With `audibleFetchBackend: \"auto\"`, it can recover from Python-client rejections by retrying the same URL through browser-like `curl`.\n\nUseful checks:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh doctor --config-path .audible-goodreads-deal-scout/config.json\nsh ./scripts/audible-goodreads-deal-scout.sh show-csv-headers \"/absolute/path/to/goodreads_library_export.csv\"\nsh ./scripts/audible-goodreads-deal-scout.sh publish-audit --version 0.1.18 --tags latest\n```\n\n`doctor` checks the configured config, CSV, notes, auth file, cache directory, delivery settings, cron settings, Audible fetch backend, local OpenClaw binary, bundled shell wrapper, and installed skill version. Add `--check-cron` to query live OpenClaw jobs and verify schedule, IANA timezone, route, condition trigger, lightweight context, and disabled thinking. Disabled related jobs are reported separately from missing jobs.\n\nAdd `--check-audible-fetch` when you want a live daily-deal fetch probe from the current host. This is opt-in because it makes a network request to Audible.\n\nIf your OpenClaw install strips executable bits from bundled scripts, run the wrapper through `sh` exactly as shown above and in `SKILL.md`.\n- Scheduled runs cannot stop for interactive exec approval. Before enabling daily automation, verify that OpenClaw exec policy allows the exact unattended cron command on your trusted host and that `cron.triggers.enabled` is intentionally enabled.\n- Before enabling `dailyAutomation` or `--register-cron`, confirm the configured delivery channel and target are the ones you actually want the skill to use through your local OpenClaw runtime.\n\n## Advanced CLI usage\n\nIf you prefer scripted setup instead of interactive setup:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh setup \\\n  --non-interactive \\\n  --config-path .audible-goodreads-deal-scout/config.json \\\n  --audible-marketplace us \\\n  --threshold 3.8 \\\n  --goodreads-csv \"/absolute/path/to/goodreads_library_export.csv\" \\\n  --notes-file \"/absolute/path/to/preferences.md\" \\\n  --delivery-channel telegram \\\n  --delivery-target \"-1000000000000\" \\\n  --delivery-policy positive_only\n```\n\nUseful helper commands:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh doctor --config-path .audible-goodreads-deal-scout/config.json\nsh ./scripts/audible-goodreads-deal-scout.sh show-csv-headers \"/absolute/path/to/goodreads_library_export.csv\"\nsh ./scripts/audible-goodreads-deal-scout.sh measure-context --goodreads-csv \"/absolute/path/to/goodreads_library_export.csv\" --output /tmp/fit-context.json\nsh ./scripts/audible-goodreads-deal-scout.sh publish-audit --version 0.1.18\n```\n\nFinalize and deliver in one step:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh run-and-deliver \\\n  --config-path .audible-goodreads-deal-scout/config.json \\\n  --prepare-json .audible-goodreads-deal-scout/artifacts/current/prepare-result.json \\\n  --runtime-output /tmp/runtime-output.json\n```\n\n## Repository structure\n\n- `SKILL.md`: agent-facing runtime instructions\n- `TRUST.md`: security, data-access, and no-purchase behavior summary\n- `agents/openai.yaml`: interface metadata and default prompt for OpenClaw agent surfaces\n- `scripts/audible-goodreads-deal-scout.sh`: bundled shell wrapper for local CLI and OpenClaw installs that may not preserve executable bits\n- `audible_goodreads_deal_scout/fit_evidence.py`: deterministic candidate-specific Goodreads evidence selection\n- `audible_goodreads_deal_scout/html_extract.py`: shared structured-data and metadata extraction for external pages\n- `audible_goodreads_deal_scout/core.py`: prep/orchestration logic\n- `audible_goodreads_deal_scout/audible_fetch.py`: guarded Audible HTTP fetching, browser-like headers, and curl fallback\n- `audible_goodreads_deal_scout/audible_auth.py`: optional headless Audible auth and API price lookup helpers\n- `audible_goodreads_deal_scout/audible_catalog.py`: Audible catalog search and conservative price parsing\n- `audible_goodreads_deal_scout/cli_errors.py`: structured CLI error payload helpers\n- `audible_goodreads_deal_scout/diagnostics.py`: local doctor/status checks\n- `audible_goodreads_deal_scout/goodreads_rating.py`: optional public Goodreads rating enrichment for Want-to-Read reports\n- `audible_goodreads_deal_scout/want_to_read_scan.py`: Goodreads Want-to-Read scan orchestration and report rendering\n- `audible_goodreads_deal_scout/runtime_contract.py`: runtime input, prompt, schema, and prepare-result artifact writing\n- `audible_goodreads_deal_scout/rendering.py`: card rendering and delivery planning\n- `audible_goodreads_deal_scout/delivery.py`: config, cron, and delivery helpers\n- `audible_goodreads_deal_scout/public_cli.py`: setup and CLI entrypoint\n- `config.example.json`: public config example\n- `examples/preferences.example.md`: sample notes file\n- `docs/release-checklist.md`: release checklist for publishable builds\n\n## Publish to ClawHub\n\nBefore publishing, run:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh publish-audit --version 0.1.18 --tags latest\n```\n\nFor public auditability, create a matching Git tag and GitHub release for each ClawHub version, for example `v0.1.18`. `publish-audit` fails when its requested version, the package version, and the changelog section do not agree.\n\n## Why this is worth publishing\n\nThe value is not just “show me today’s Audible promotion.”\n\nThe real value is:\n- filtering instead of promo noise\n- combining public quality with personal fit\n- respecting `read`, `currently-reading`, and `to-read`\n- optional proactive delivery into a real channel\n- graceful handling of suppressions and lookup failures\n\nFile v0.1.18:_meta.json\n\n{\n  \"ownerId\": \"kn74j40rqb6m5s0whvynrxcq098212ny\",\n  \"slug\": \"audible-goodreads-deal-scout\",\n  \"version\": \"0.1.18\",\n  \"publishedAt\": 1784518180028\n}\n\nFile v0.1.18:CHANGELOG.md\n\n# Changelog\n\n## Unreleased\n\n## 0.1.18 - 2026-07-19\n\n- Add a deterministic scheduled gate so positive-only suppressions do not start an agent or create cron run history\n- Use OpenClaw condition triggers, lightweight bootstrap context, and disabled model thinking for substantially smaller scheduled runs\n- Reconcile and diagnose cron trigger, context, schedule, IANA timezone, and delivery-route drift; support explicit automation and route removal\n- Preserve unknown and marketplace-specific config values, resolve configured relative paths from the config directory, and fail closed on malformed config or state\n- Bind scheduled delivery and state updates to the config/state paths recorded by the current prepare artifact\n- Harden Audible auth storage, refresh-token rotation, permissions, schema checks, redirect handling, response bounds, and sensitive-data redaction\n- Validate public HTTP redirects before following them, bound compressed/decompressed responses, and tighten Audible and Goodreads URL paths\n- Prefer strong Audible catalog matches regardless of candidate order and restrict Goodreads aggregate ratings to valid Book entities\n- Validate scan bounds, preflight authenticated scans, preserve zero-valued options, and return partial-failure exit codes reliably\n- Make delivery success and dry-run results unambiguous and reject successful exit codes carrying failure payloads\n- Audit the actual ClawHub publish bundle, require every runtime module, and enforce package/changelog/release-version parity\n- Add regression and permutation coverage for security, setup, scheduling, state, parsing, delivery, publishing, and scan failure boundaries\n\n## 0.1.17\n\n- Publish the post-0.1.16 test release pointer used to verify ClawHub release metadata\n- Build a bounded candidate-specific fit-evidence artifact and require more concrete, review-grounded recommendation prose\n- Strictly validate runtime output fields, types, Goodreads URLs, rating ranges, fit status semantics, and fit paragraph length\n- Split preparation into focused fetch, library, short-circuit, and artifact phases and remove implicit `core` re-exports\n- Harden Audible and Goodreads parsers for JSON-LD graphs, markup attribute variants, nested text, lowercase product ids, and trailing price punctuation\n- Surface OpenClaw command timeouts and invalid JSON instead of treating ambiguous subprocess output as success or an empty cron list\n- Split the test suite by behavior and add DST, expiry, cache, atomic-write, subprocess, parser-variant, and evidence-selection coverage\n- Exclude `PROMPT_REQUEST.md` from the published ClawHub runtime bundle\n\n## 0.1.16\n\n- Route registered OpenClaw cron jobs through the configured delivery channel and target\n- Reconcile existing Audible cron jobs when their schedule, IANA timezone, message, or delivery route drifts\n- Make live cron diagnostics fail on active schedule or delivery mismatches\n\n## 0.1.15\n\n- Preserve existing config values when rerunning setup or registering cron from an existing config path\n- Prevent cron registration from accidentally dropping Goodreads CSV, delivery, auth, or CSV column settings when omitted from a follow-up setup command\n- Clarify that unattended OpenClaw/Codex cron runs need a non-interactive command-approval policy on trusted local hosts\n\n## 0.1.14\n\n- Resolve the OpenClaw CLI from common user install locations such as `~/.npm-global/bin/openclaw` when non-interactive PATHs omit it\n- Add a `version` command and include `skillVersion` in `doctor` output for installed-bundle checks\n- Improve live cron diagnostics so disabled related jobs are reported separately from missing jobs\n- Declare `sh` in skill requirements because the documented launcher uses the shell wrapper\n\n## 0.1.13\n\n- Keep optional cookie-style Audible auth registration for member-visible prices without persisting website/store cookie payloads\n- Add auth status metadata that explains the credential purpose and allowed use without exposing token contents\n- Expand trust and README guidance for optional Audible authentication, including refresh-token and cookie-style credential handling\n\n## 0.1.12\n\n- Restrict Audible fetches to known HTTPS Audible hosts and daily-deal/search/product paths before either Python or curl can request them\n- Add `doctor --check-audible-fetch` as an opt-in live host probe for the daily-deal fetch path\n- Extract browser-like Audible fetch backends into `audible_fetch.py` and remove the legacy contract harness in favor of the public CLI commands\n- Split shared test fixtures and Audible fetch tests out of the main test module\n\n## 0.1.11\n\n- Always write a fresh `artifacts/current/prepare-result.json` for ready, suppress, and error prepare outcomes so failed current-day prep cannot leave a stale deliverable artifact behind\n- Refuse scheduled `run-and-deliver` attempts for error prep results or stale scheduled artifacts whose `metadata.storeLocalDate` no longer matches the current Audible marketplace date\n- Make `mark-emitted` validate the delivered scheduled prepare artifact and mark only its current `metadata.dealKey`\n- Use browser-like Audible daily-promotion request headers, including `Accept-Language`, to reduce avoidable 503 responses\n\n## 0.1.10\n\n- Add `TRUST.md` with data-access, network, optional auth, privacy-mode, and no-purchase behavior documentation\n- Surface data-access and no-purchase disclosures in `SKILL.md` for the ClawHub-visible page\n- Align `SKILL.md` license metadata with ClawHub's MIT-0 skill license\n- Update release guidance to create matching Git tags and GitHub releases for ClawHub versions\n\n## 0.1.9\n\n- Add a human-facing ClawHub overview to `SKILL.md` so the marketplace README tab explains the skill before agent runtime instructions\n- Keep agent-facing operational instructions under a dedicated runtime section\n- Update release metadata defaults for the marketplace-rendering fix\n\n## 0.1.8\n\n- Refresh ClawHub README and release metadata\n\n## 0.1.7\n\n- Add stderr progress reporting for long Want-to-Read scans, including JSONL mode for OpenClaw agents and log processors\n- Suppress duplicate Audible product matches in final Want-to-Read reports while preserving scanned-row counts and duplicate metadata in JSON\n- Add scan report metadata for authenticated-pricing state, cache stats, request usage, and next-batch hints\n- Add `priceBasis` and `dealType` fields so reports can distinguish member cash prices below list from limited-time sale or promotion signals\n- Enrich missing Goodreads average ratings for a capped number of discounted Want-to-Read results by Goodreads book id\n- Retry transient daily-promotion fetch failures and temporary no-active-promotion parses before suppressing or erroring\n- Add setup `nextSteps` guidance and strengthen publish-audit checks for generated/private artifact exclusions\n- Clarify that authenticated `discounted` means member-visible cash price below list price, not guaranteed limited-time sale status\n- Improve release and troubleshooting docs for long scans, authenticated price lookup, and local readiness checks\n- Reduce duplicated scan-progress bookkeeping in the Want-to-Read scan implementation\n\n## 0.1.5\n\n- Add stdlib-only headless Audible external-login auth helpers for optional authenticated price lookup\n- Add authenticated Audible catalog product pricing lookup for matched Want-to-Read scan results\n- Add `--audible-auth-path` to `scan-want-to-read` and helper commands for auth start, finish, and one-ASIN price testing\n- Add `doctor` and `audible-auth-status` commands for local readiness, auth expiry, and file-permission checks\n- Add structured CLI error payloads with token redaction for command failures\n- Ignore Audible credit prices when classifying authenticated cash discounts\n- Clarify external-browser auth instructions and authenticated request budgeting\n- Move prepare-result artifact writing behind the runtime contract module boundary\n- Keep auth files out of published bundles and document that the auth file is sensitive local state\n\n## 0.1.4\n\n- Add a manual `scan-want-to-read` command for checking Goodreads `to-read` books against visible Audible US numeric discounts\n- Add conservative Audible catalog search, pricing parsing, parsed-result cache, request budgeting, and block-like circuit breaker handling for the new scan\n- Add compact Markdown and structured JSON reports for Want-to-Read discount scans\n- Add offline fixture coverage for scan selection, matching, pricing, request budget behavior, cached block failures, and compact report output\n\n## 0.1.3\n\n- Invoke the published shell wrapper through `sh` in `SKILL.md` and README examples so official OpenClaw installs still work even when the installed script loses its executable bit\n- Clarify that default config, state, and artifact storage belongs under `.audible-goodreads-deal-scout/` in the active OpenClaw workspace, not inside the installed skill folder or under the legacy `.audible-goodreads-deal` name\n- Clarify in the README that configured CSV, notes, config, and state paths should only point at files the user intends the skill to read or write\n- Add README guidance to review delivery settings before enabling daily automation or cron registration\n- Soften transaction-heavy README wording for a skill that evaluates promotions rather than making purchases\n- Add a release-check step to verify the live ClawHub license summary matches `SKILL.md` and `LICENSE.txt`\n\n## 0.1.2\n\n- Rename the published shell wrapper to `scripts/audible-goodreads-deal-scout.sh` so the ClawHub bundle exposes the documented entrypoint\n- Rename the repository license file to `LICENSE.txt` and require it in the publish audit so extensionless files do not disappear from published bundles\n- Update release guidance to verify the published wrapper and license files after upload\n\n## 0.1.1\n\n- Move the published wrapper entrypoint from `bin/` to `scripts/` so the package layout matches ClawHub skill conventions\n- Update SKILL and README command examples to use the published `scripts/audible-goodreads-deal-scout` wrapper path\n- Add release guidance to verify the published file manifest after upload\n\n## 0.1.0\n\n- Initial public release candidate for `audible-goodreads-deal-scout`\n- Audible daily-promotion evaluation with Goodreads public score\n- Optional Goodreads CSV shelf logic\n- Optional freeform taste notes\n- Delivery policy support for positive-only, full, and summary delivery\n- Publish-time privacy audit\n- Marketplace certification fixtures and runtime-contract tests\n\nFile v0.1.18:examples/preferences.example.md\n\nI usually like fiction that is idea-driven, formally interesting, and emotionally controlled rather than sentimental.\n\nAuthors and books I tend to like:\n- Ursula K. Le Guin\n- George Orwell\n- Kazuo Ishiguro\n- David Mitchell\n- literary science fiction\n- political satire\n- speculative fiction with philosophical weight\n\nWhat I usually do not like:\n- generic airport thrillers\n- fantasy that is mostly lore and worldbuilding\n- romance-forward plots\n- books that rely on shock value more than ideas\n\nWhen in doubt, I prefer:\n- originality over comfort\n- structure and voice over plot mechanics\n- books that leave something to think about afterward\n\nFile v0.1.18:skill-card.md\n\n## Description:\n\nEvaluate an Audible daily promotion against Goodreads public score, optional Goodreads CSV shelves, optional freeform reading notes, optional delivery rules, and manual Want-to-Read discount scans.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[lenpr](https://clawhub.ai/user/lenpr)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nExternal users and developers use this skill to set up Audible deal checks, compare promotions against public Goodreads ratings and optional personal reading data, scan Goodreads Want-to-Read shelves for visible Audible discounts, and optionally route matching results to a configured delivery channel.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill can read configured Goodreads CSV files, taste notes, delivery targets, generated state, and optional Audible auth files.\n\nMitigation: Point configuration only at intended files, use privacyMode minimal when personal reading data should not be used in the model step, and keep local state out of published bundles.\n\nRisk: An optional Audible auth file contains sensitive bearer and refresh token material for member-visible price lookup.\n\nMitigation: Create auth only through the provided helper flow, keep the file private, do not paste or commit it, and use status checks that avoid printing token values.\n\nRisk: Optional delivery and daily automation can send results or execute scheduled checks without interactive review.\n\nMitigation: Enable delivery and cron triggers only on a trusted OpenClaw host you control, confirm the configured channel and target, and disable automation when it is no longer needed.\n\nRisk: Audible pricing and Goodreads matching can be incomplete or ambiguous when pages hide cash prices, change layout, or expose uncertain matches.\n\nMitigation: Treat hidden, unknown, needs-review, and non-match statuses as uncertainty, and keep any audiobook purchase decision manual and outside the skill.\n\n## Reference(s):\n\n- [ClawHub Skill Page](https://clawhub.ai/lenpr/skills/audible-goodreads-deal-scout)\n- [Source Homepage](https://github.com/lenpr/audible-goodreads-deal-scout)\n- [README](README.md)\n- [Trust and Data Access](TRUST.md)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Markdown, JSON, Shell commands, Configuration, Guidance]\n\n**Output Format:** [Markdown and text recommendations, JSON runtime contracts, shell commands, and optional report files or delivery messages]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Outputs may include setup guidance, daily-deal recommendations, non-match summaries, Want-to-Read scan reports, diagnostics, and delivery-ready messages.]\n\n## Skill Version(s):\n\n0.1.18 (source: server release metadata, changelog released 2026-07-19, package __version__)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nFile v0.1.18:TRUST.md\n\n# Trust and Data Access\n\nAudible Goodreads Deal Scout is a ClawHub / OpenClaw skill for evaluating Audible deals against Goodreads data and optional personal taste notes.\n\nIt reports deal opportunities. It does not buy, reserve, check out, redeem credits, manage subscriptions, or complete purchases.\n\n## What the skill may read\n\n| Input | When used | Why |\n| --- | --- | --- |\n| Config file | Setup, daily deal checks, Want-to-Read scans, delivery | Stores marketplace, thresholds, paths, privacy mode, and optional delivery settings |\n| Goodreads CSV | Only when configured | Detects read/currently-reading/to-read shelves and uses ratings/reviews for fit |\n| Notes file or pasted notes | Only when configured | Adds personal reading preferences for fit explanations |\n| Audible auth file | Only when explicitly created and passed | Checks member-visible cash prices for matched Audible titles |\n| Generated artifacts/cache/state | During normal operation | Keeps deterministic prep output, report output, cached lookups, and duplicate scheduled-run state |\n\nOnly point configured paths at files you intend this skill to read.\n\nRelative paths in the JSON config resolve from that config file's directory. The runtime fails closed on malformed config, malformed scheduled state, and configured input files that are missing or unreadable.\n\n## What the skill may write\n\n| Output | Location |\n| --- | --- |\n| Config, state, reports, artifacts, and cache files | The configured storage directory, normally `.audible-goodreads-deal-scout/` in the active OpenClaw workspace |\n| Optional delivery messages | A configured OpenClaw channel and target, only when delivery is enabled or requested |\n| Optional cron entries and condition script | OpenClaw cron and the config storage directory, only when daily automation registration is requested |\n\nThe skill should not write mutable user state inside the installed skill folder because OpenClaw can replace that folder during updates.\n\n## Network access\n\nThe skill may fetch:\n\n- Audible promotion, search, and product pages\n- Audible authenticated product-price API responses when an Audible auth file is explicitly supplied\n- Goodreads public pages for runtime score resolution and optional rating enrichment\n\nUnauthenticated Audible HTML fetches are guarded to known HTTPS Audible hosts and daily-deal, search, or product paths before either the Python fetch path or curl fallback can request them. Python redirects are validated before they are followed; the curl fallback refuses redirects. Audible and Goodreads response bodies and decompression output are bounded.\n\nIt does not send data to a private server controlled by this repository.\n\n## Optional Audible authentication\n\nAudible authentication is optional. The skill works without it, but anonymous Audible pages often hide cash prices behind credit or membership UI.\n\nIf you choose to use authenticated price lookup:\n\n- the skill creates a local auth file through the `audible-auth-start` and `audible-auth-finish` helper flow\n- the auth flow requests cookie-style Audible/Amazon credential types for compatibility because anonymous Audible pages often hide member cash prices\n- the auth file persists the bearer access/refresh token fields used for token refresh and product-price lookup\n- the auth file is sensitive local state and should not be committed, pasted into chat, or published\n- ready auth files must be regular, non-symlink files with owner-only permissions\n- the auth file is used only for token refresh and Audible product-price lookup\n- authenticated API calls are restricted in code to validated Audible product ids and allowlisted Audible/Amazon API domains\n- authenticated `discounted` means a member-visible cash price is below list price, not proof of a limited-time sale\n\n## Purchase behavior\n\nThe skill does not make purchases.\n\nIt does not:\n\n- add items to a cart\n- buy audiobooks\n- redeem credits\n- reserve deals\n- manage subscriptions\n- submit payment information\n\nAny purchase decision remains manual and outside the skill.\n\n## Privacy modes\n\n`privacyMode: \"normal\"` allows the model-facing fit step to use configured Goodreads context and taste notes.\n\n`privacyMode: \"minimal\"` prevents personal artifacts from being exposed to the model-facing runtime and produces recommendations from public data only.\n\n## Scheduled execution\n\nDaily registration uses an OpenClaw condition trigger to run deterministic preparation before an agent turn. Under the default `positive_only` policy, duplicate and deterministic non-match results return `fire: false`, avoiding a model run. Agent turns that are still required use lightweight bootstrap context with thinking disabled.\n\nOpenClaw condition triggers can execute tools without supervision. `cron.triggers.enabled` should remain disabled unless the host, cron-authoring agents, local skill installation, and command approval policy are all trusted. Disabling automation through setup clears the related trigger and fallback delivery route.\n\n## Publishing safety\n\nPublished bundles should exclude local/generated state, auth files, caches, tests, and private artifacts. Run before publishing:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh publish-audit --tags latest\n```\n\nThe publish audit checks required public files, generated/private artifact exclusions, and known private marker leaks.\n\nFile v0.1.18:config.example.json\n\n{\n  \"artifactDir\": \"artifacts/current\",\n  \"audibleAuthPath\": null,\n  \"audibleDealUrl\": null,\n  \"audibleFetchBackend\": \"auto\",\n  \"audibleFetchBackoffSeconds\": 1.0,\n  \"audibleFetchRetries\": 2,\n  \"audibleMarketplace\": \"us\",\n  \"csvColumns\": {},\n  \"dailyCron\": \"15 1 * * *\",\n  \"deliveryChannel\": null,\n  \"deliveryPolicy\": \"positive_only\",\n  \"deliveryTarget\": null,\n  \"freshnessDays\": 180,\n  \"enrichGoodreadsRatings\": true,\n  \"goodreadsRatingLimit\": 20,\n  \"goodreadsCsvPath\": \"goodreads_library_export.csv\",\n  \"preferencesPath\": \"preferences.md\",\n  \"privacyMode\": \"normal\",\n  \"stateFile\": \"state.json\",\n  \"threshold\": 3.8\n}\n\nFile v0.1.18:agents/openai.yaml\n\ninterface:\n  display_name: \"Audible Deal Scout\"\n  short_description: \"Check an Audible daily promotion against Goodreads score, shelves, notes, and delivery rules\"\n  default_prompt: \"Use $audible-goodreads-deal-scout to set up or evaluate an Audible daily promotion, then finalize and optionally deliver the result.\"\n\nFile v0.1.18:LICENSE.txt\n\nMIT License\n\nCopyright (c) 2026 Lukas N.P. Egger\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\nArchive v0.1.17: 31 files, 107373 bytes\n\nFiles: agents/openai.yaml (317b), audible_goodreads_deal_scout/__init__.py (209b), audible_goodreads_deal_scout/audible_auth.py (24001b), audible_goodreads_deal_scout/audible_catalog.py (30928b), audible_goodreads_deal_scout/audible_fetch.py (18079b), audible_goodreads_deal_scout/audible_source.py (11790b), audible_goodreads_deal_scout/cli_errors.py (878b), audible_goodreads_deal_scout/constants.py (2361b), audible_goodreads_deal_scout/core.py (47046b), audible_goodreads_deal_scout/delivery.py (20103b), audible_goodreads_deal_scout/diagnostics.py (13820b), audible_goodreads_deal_scout/goodreads_csv.py (6509b), audible_goodreads_deal_scout/goodreads_rating.py (5119b), audible_goodreads_deal_scout/public_cli.py (31845b), audible_goodreads_deal_scout/rendering.py (8792b), audible_goodreads_deal_scout/repo_audit.py (1512b), audible_goodreads_deal_scout/runtime_contract.py (7829b), audible_goodreads_deal_scout/settings.py (5444b), audible_goodreads_deal_scout/shared.py (6818b), audible_goodreads_deal_scout/want_to_read_scan.py (32203b), CHANGELOG.md (7917b), config.example.json (726b), examples/preferences.example.md (644b), LICENSE.txt (1073b), PROMPT_REQUEST.md (29654b), README.md (29233b), scripts/audible-goodreads-deal-scout.sh (541b), skill-card.md (2530b), SKILL.md (15922b), TRUST.md (4180b), _meta.json (148b)\n\nFile v0.1.17:SKILL.md\n\n---\nname: audible-goodreads-deal-scout\ndescription: Evaluate an Audible daily promotion against Goodreads public score, optional Goodreads CSV shelves, optional freeform reading notes, optional delivery rules, and manual Want-to-Read discount scans. Use for first-run setup, deal checks, scheduled sends, and on-demand Goodreads backlog audits.\nlicense: MIT-0\nmetadata: {\"openclaw\":{\"emoji\":\"🎧\",\"skillKey\":\"audible-goodreads-deal-scout\",\"homepage\":\"https://github.com/lenpr/audible-goodreads-deal-scout\",\"category\":\"media\",\"requires\":{\"bins\":[\"sh\"],\"anyBins\":[\"python3\",\"python\"]}}}\n---\n\n# Audible Goodreads Deal Scout\n\nNever miss an Audible deal for a book you actually want to read.\n\nAudible Goodreads Deal Scout is a **ClawHub / OpenClaw skill** that checks Audible promotions against Goodreads ratings, your Goodreads shelves, and optional reading-taste notes. It is built for people who want fewer random deal notifications and more \"this is actually relevant to me\" recommendations.\n\nThe goal is not to buy more audiobooks. The goal is to notice the few Audible deals that match books you already care about.\n\n## What It Does\n\nUse this skill to:\n- check today's Audible daily deal and get a short recommendation\n- see whether the deal is already on your Goodreads Want-to-Read shelf\n- suppress books you already marked as read or currently reading\n- scan your Goodreads Want-to-Read shelf for Audible titles with visible discounts\n- rank discounted Want-to-Read matches by deal strength and Goodreads signal\n- create personalized recommendations from your Goodreads shelves, ratings, reviews, and taste notes\n- explain why a book may or may not fit your reading preferences, instead of only showing a generic score\n- optionally check member-visible Audible cash prices with a local Audible auth token\n- optionally deliver good matches to Telegram or another configured OpenClaw channel\n\nIf you do not want personalization, the skill still works with public Goodreads ratings only.\n\nThis skill reports opportunities only. It does not buy, reserve, check out, redeem credits, manage subscriptions, or complete purchases.\n\n## Getting The Most Value\n\nThe best setup uses:\n1. A Goodreads library CSV from the official Goodreads `Import and Export` page.\n2. Short taste notes about books, authors, genres, pacing, and themes you like or avoid.\n3. Optional Audible authentication when you want member-visible cash prices in Want-to-Read scans.\n\nWith those pieces, the skill can track today's Audible promotion, compare it against your Goodreads library, explain personal fit, and scan your Want-to-Read shelf for Audible titles that look discounted or priced below list.\n\n## Trust And Data Access\n\nThe skill reads only the files and services needed for its configured workflow.\n\n| Data or service | When used | Purpose |\n| --- | --- | --- |\n| Config file | Setup, daily checks, scans, delivery | Stores marketplace, thresholds, paths, privacy mode, and optional delivery settings |\n| Goodreads CSV | Only when configured | Detects `read`, `currently-reading`, and `to-read` shelves and uses ratings/reviews for fit |\n| Taste notes | Only when configured | Adds personal reading preferences for fit explanations |\n| Audible pages | Deal checks and Want-to-Read scans | Fetches daily promotions, search results, product pages, and visible pricing signals |\n| Audible auth file | Optional, explicit authenticated scans only | Checks member-visible cash prices for matched Audible titles through allowlisted token-refresh and Audible product-pricing API calls |\n| Goodreads public pages | Runtime lookup and optional rating enrichment | Resolves public rating evidence and fills missing Want-to-Read average ratings |\n| OpenClaw CLI | Optional delivery, cron, and diagnostics | Sends configured messages, registers requested cron jobs, and checks local readiness |\n\nThe local auth file is sensitive. Do not paste its contents into chat, commit it, or publish it. The auth flow requests cookie-style Audible/Amazon credential types for compatibility because anonymous pages may hide member cash prices, but the skill persists only the bearer access/refresh token fields it uses for token refresh and Audible product-price lookup.\n\nFor a fuller trust and data-access summary, see `TRUST.md` in the published bundle or repository.\n\n## Optional Audible Authentication\n\nAudible authentication is optional and separate from the normal daily-deal workflow. The skill works without it, but anonymous Audible pages often hide cash prices behind credit or membership UI.\n\nUse authenticated price lookup only when the user explicitly wants member-visible cash prices in Want-to-Read scans. Do not ask for the user's Audible or Amazon password. Use `audible-auth-start`, `audible-auth-finish`, and `audible-auth-status` instead. Never read or display the auth file contents; status commands intentionally report readiness, expiry, permissions, and allowed-use metadata without token values.\n\n## Agent Runtime Instructions\n\nUse this skill when the user wants to:\n- set up a reusable Audible deal workflow\n- check the current Audible daily promotion\n- scan Goodreads Want-to-Read books for visible Audible US discounts\n- personalize the result with a Goodreads CSV and/or freeform notes\n- finalize and optionally deliver the result into a configured channel\n\n## Runtime output contract\n\nThe skill runtime must return JSON only in this shape:\n\n```json\n{\n  \"schemaVersion\": 1,\n  \"goodreads\": {\n    \"status\": \"resolved | no_match | lookup_failed\",\n    \"url\": \"string | null\",\n    \"title\": \"string | null\",\n    \"author\": \"string | null\",\n    \"averageRating\": \"number | null\",\n    \"ratingsCount\": \"integer | null\",\n    \"evidence\": \"string | null\"\n  },\n  \"fit\": {\n    \"status\": \"written | not_applicable | unavailable\",\n    \"sentence\": \"string | null\"\n  }\n}\n```\n\n## Use the Python prep layer first\n\nDo not fetch Audible yourself in model text. Always start with the prep layer:\n\n```bash\nsh \"{baseDir}/scripts/audible-goodreads-deal-scout.sh\" prepare --config-path \"<config-path>\" --invocation-mode manual\n```\n\nBy default, `prepare` uses `audibleFetchBackend: auto`: guard the URL against non-Audible destinations, try Python fetch first, then use browser-like `curl` fallback for recoverable Audible HTTP failures such as Python-client `503` rejections. Use `--audible-fetch-backend python` or `--audible-fetch-backend curl` only for explicit diagnostics.\n\nPrep returns JSON with:\n- `status: ready | suppress | error`\n- `reasonCode`\n- `warnings[]`\n- `audible`\n- `personalData`\n- `artifacts`\n- `metadata`, including `metadata.fetch` when fetch diagnostics are available\n\nIf prep returns `suppress` or `error`, surface that result directly and stop. Do not do Goodreads lookup or fit writing after a prep-layer short-circuit.\n\n## Setup\n\nIf the skill is not configured yet, gather:\n1. Audible store\n2. Whether the user wants personalization\n3. Optional Goodreads CSV path\n4. Optional notes file or pasted notes\n5. Optional threshold override from the default `3.8`\n6. Optional delivery channel and target\n7. Delivery policy: `positive_only`, `always_full`, or `summary_on_non_match`\n8. Whether daily automation should be enabled\n\nThen write config through:\n\n- If the user does not request a custom path, use the default workspace-root storage path: `<workspace>/.audible-goodreads-deal-scout/`.\n- Do not invent legacy names like `.audible-goodreads-deal`.\n- Do not store mutable config, state, or artifacts inside `{baseDir}` or the installed skill folder. `openclaw skills install` and `openclaw skills update --force` replace the workspace skill directory.\n\n```bash\nsh \"{baseDir}/scripts/audible-goodreads-deal-scout.sh\" setup \\\n  --config-path \"<config-path>\" \\\n  --audible-marketplace \"<marketplace>\" \\\n  --threshold \"<threshold>\" \\\n  [--goodreads-csv \"<csv-path>\"] \\\n  [--notes-file \"<notes-file>\"] \\\n  [--notes-text \"<inline notes>\"] \\\n  [--delivery-channel \"telegram\"] \\\n  [--delivery-target \"<target>\"] \\\n  [--delivery-policy \"positive_only\"] \\\n  [--daily-automation] \\\n  [--register-cron]\n```\n\nUse interactive `setup` only when the user explicitly wants prompt-by-prompt CLI onboarding. Otherwise prefer the non-interactive command with concrete flags.\n\nBefore enabling daily automation, make sure the user's OpenClaw host can run scheduled exec commands unattended. Cron runs cannot wait for Telegram or app-server command approval. On a trusted local OpenClaw box, the user may need an explicit Codex app-server policy such as `plugins.entries.codex.config.appServer.approvalPolicy: \"never\"` with `sandbox: \"danger-full-access\"`, or an equivalent allowlist for the exact shell command OpenClaw uses.\n\n## Want-to-Read discount scan\n\nUse this only when the user asks to scan Goodreads Want-to-Read books for Audible discounts. This is a manual audit command, not a cron or delivery workflow.\n\nRequirements:\n- The configured Goodreads CSV must exist.\n- V1 supports Audible US only.\n- Do not create cron jobs or send delivery messages for this command.\n- Do not perform extra model web searches; the Python command handles Audible lookup and report generation.\n- If setup or runtime state is unclear, run `doctor` before retrying.\n\nRun:\n\n```bash\nsh \"{baseDir}/scripts/audible-goodreads-deal-scout.sh\" scan-want-to-read \\\n  --config-path \"<config-path>\" \\\n  [--audible-auth-path \"<auth-path>\"] \\\n  [--limit 40] \\\n  [--offset 0] \\\n  [--scan-order newest] \\\n  [--progress plain] \\\n  [--no-goodreads-rating-enrichment] \\\n  [--goodreads-rating-limit 20] \\\n  [--output-json \"<json-path>\"] \\\n  [--output-md \"<markdown-path>\"]\n```\n\nDefault behavior:\n- Print compact Markdown to stdout.\n- Write progress to stderr by default. Use `--progress json` for machine-readable JSONL progress or `--progress none` when silence is required.\n- Show visible numeric discounts first.\n- Suppress long non-deal lists unless `--include-non-deals` is requested.\n- Suppress duplicate Audible product matches in the final report while preserving scanned-row counts.\n- Use `--offset` and `--limit` for large Goodreads backlogs.\n- For long agent-run scans, prefer `--progress json` plus `--output-json` and `--output-md` so progress logs and final reports stay separate.\n- Use `pricing.priceBasis` and `pricing.dealType` to distinguish member cash prices below list from true limited-time sale or promotion signals.\n- If CSV average ratings are missing, the command may enrich a small number of discounted rows from public Goodreads book pages by Goodreads book id. Disable with `--no-goodreads-rating-enrichment` when the user wants no Goodreads page fetches.\n\nImportant caveat: Audible often hides cash prices behind credit or membership UI. Treat `price_hidden`, `price_unknown`, and `needs_review` as honest uncertainty, not as failures.\n\nOptional authenticated pricing:\n- If the user asks for headless authenticated Audible prices, use `audible-auth-start` and `audible-auth-finish`.\n- Do not ask for the user's Audible or Amazon password.\n- Store the auth file under the workspace storage directory, for example `<workspace>/.audible-goodreads-deal-scout/audible-auth.json`.\n- Treat the auth file as sensitive and never paste its token contents into chat.\n- Authenticated lookup is code-restricted to validated 10-character Audible product ids, token refresh, and allowlisted Audible/Amazon API domains.\n- Authenticated scans usually spend one search request plus one authenticated price request for each matched title; set `--max-requests` accordingly.\n- Treat cash pricing fields as the source of truth and do not classify Audible credit prices, including `credit_price`, as cash discounts.\n- Treat authenticated `discounted` as \"member-visible cash price below list price\", not proof of a limited-time sale; check `pricing.dealType`.\n- Use `audible-auth-status` to check readiness, expiry, and file permissions without exposing tokens.\n\n```bash\nsh \"{baseDir}/scripts/audible-goodreads-deal-scout.sh\" audible-auth-start \\\n  --auth-path \"<workspace>/.audible-goodreads-deal-scout/audible-auth.json\" \\\n  --audible-marketplace us\n\nsh \"{baseDir}/scripts/audible-goodreads-deal-scout.sh\" audible-auth-finish \\\n  --auth-path \"<workspace>/.audible-goodreads-deal-scout/audible-auth.json\" \\\n  --redirect-url \"<final-amazon-redirect-url>\"\n```\n\nTroubleshooting:\n\n```bash\nsh \"{baseDir}/scripts/audible-goodreads-deal-scout.sh\" doctor \\\n  --config-path \"<config-path>\"\n\nsh \"{baseDir}/scripts/audible-goodreads-deal-scout.sh\" audible-auth-status \\\n  --auth-path \"<workspace>/.audible-goodreads-deal-scout/audible-auth.json\"\n```\n\nTo verify the installed bundle version:\n\n```bash\nsh \"{baseDir}/scripts/audible-goodreads-deal-scout.sh\" version\n```\n\nUse `doctor --check-audible-fetch` only when the user wants a live host probe of the Audible daily-deal fetch path.\n\n## Ready flow\n\nFor `ready_*` prep results:\n1. Read `artifacts.runtimePromptPath`\n2. Read `artifacts.runtimeInputPath`\n3. Resolve the Goodreads public book page and score with OpenClaw web/search\n4. Produce JSON only that matches `artifacts.runtimeOutputSchemaPath`\n5. Finalize through:\n\n```bash\nsh \"{baseDir}/scripts/audible-goodreads-deal-scout.sh\" finalize \\\n  --prepare-json \"<prepare-result-path>\" \\\n  --runtime-output \"<runtime-output-path>\"\n```\n\nIf the user wants the result routed to a configured channel:\n\n```bash\nsh \"{baseDir}/scripts/audible-goodreads-deal-scout.sh\" run-and-deliver \\\n  --config-path \"<config-path>\" \\\n  --prepare-json \"<prepare-result-path>\" \\\n  --runtime-output \"<runtime-output-path>\"\n```\n\n## Decision rules\n\n- If `personalData.exactShelfMatch == \"to-read\"`, recommend immediately. This overrides the Goodreads threshold.\n- If prep already marked the book as `read` or `currently-reading`, do not continue.\n- Otherwise enforce the Goodreads threshold from `metadata.threshold`.\n- If Goodreads lookup fails, use `error_goodreads_lookup_failed`.\n- If Goodreads cannot confirm a matching book page, use `suppress_no_goodreads_match`.\n\nSkill-layer reason codes:\n- `recommend_to_read_override`\n- `recommend_public_threshold`\n- `suppress_below_goodreads_threshold`\n- `suppress_no_goodreads_match`\n- `error_goodreads_lookup_failed`\n\n## Fit writing\n\nThe model writes the fit paragraph. Python does not call a provider API directly.\n\nUse:\n- Goodreads public score\n- `artifacts.fitContextPath`\n- `artifacts.reviewSourcePath` when present\n- `artifacts.notesPath` when present\n\nRules:\n- Do not drop rated/reviewed CSV rows for prompt convenience.\n- Summarize each written Goodreads review to 500 characters or fewer before using it as evidence.\n- If `personalData.privacyMode == \"minimal\"`, do not use personal CSV or notes content in the fit paragraph.\n- If no meaningful personal data exists, say so explicitly instead of inventing taste evidence.\n\nFallback lines:\n- `Fit: No personal preference data was configured, so this recommendation is based only on the public Goodreads score.`\n- `Fit: Personalized fit feedback is unavailable right now, but the recommendation decision still completed.`\n\n## Delivery\n\n`run-and-deliver` must respect the configured `deliveryPolicy`:\n- `positive_only`: deliver only `recommend`\n- `always_full`: deliver the full card for every final status\n- `summary_on_non_match`: deliver full `recommend`, but a short summary card for `suppress` or `error`\n\nFor scheduled runs, prep with `--invocation-mode scheduled`. If prep returns `suppress_duplicate_scheduled_run`, stop quietly. After a surfaced scheduled result, mark the deal as emitted with:\n\n```bash\nsh \"{baseDir}/scripts/audible-goodreads-deal-scout.sh\" mark-emitted \\\n  --state-file \"<state-file>\" \\\n  --prepare-json \"<prepare-result-path>\" \\\n  --deal-key \"<deal-key>\"\n```\n\nUse the same current scheduled prepare artifact that was delivered. `run-and-deliver` refuses scheduled error prep results and stale scheduled artifacts whose `metadata.storeLocalDate` is not the current Audible marketplace date.\n\nFile v0.1.17:README.md\n\n# Audible Goodreads Deal Scout\n\nNever miss an Audible deal for a book you actually want to read.\n\nAudible Goodreads Deal Scout is a **ClawHub / OpenClaw skill** that checks Audible promotions against Goodreads ratings, your Goodreads shelves, and optional reading-taste notes. It is built for people who want fewer random deal notifications and more \"this is actually relevant to me\" recommendations.\n\nThe goal is not to buy more audiobooks. The goal is to notice the few Audible deals that match books you already care about.\n\nThe skill reports opportunities only. It does not buy, reserve, check out, redeem credits, manage subscriptions, or complete purchases.\n\nFor a concise security and data-access summary, see [TRUST.md](TRUST.md).\n\n## Use This Skill To\n\nUse this skill to:\n\n- Check today's Audible daily deal and get a short recommendation.\n- See whether the deal is already on your Goodreads Want-to-Read shelf.\n- Suppress books you already marked as read or currently reading.\n- Scan your Goodreads Want-to-Read shelf for Audible titles with visible discounts.\n- Rank discounted Want-to-Read matches by deal strength and Goodreads signal.\n- Create highly personalized recommendations from your Goodreads shelves, ratings, reviews, and taste notes.\n- Explain why a book may or may not fit your reading preferences, instead of only showing a generic score.\n- Optionally check member-visible Audible cash prices with a local Audible auth token.\n- Optionally deliver good matches to Telegram or another configured OpenClaw channel.\n\nIf you do not want personalization, the skill still works with public Goodreads ratings only.\n\n## How To Get The Most Value\n\nThe skill works with public data only, but it gets much better when you give it a little personal context.\n\nThe best setup is:\n\n1. Export your Goodreads library CSV.\n   Use the official Goodreads library exporter from Goodreads' `Import and Export` page. This lets the skill know what you already read, what you are currently reading, and what is on your Want-to-Read shelf.\n2. Add short taste notes.\n   A few paragraphs are enough. You can write them yourself, dictate them quickly, or ask an AI to draft taste notes from your favorite books, disliked books, preferred genres, and reading habits. These notes help the skill explain whether a deal actually fits you, not just whether it is popular.\n3. Optionally add Audible authentication for member prices.\n   Anonymous Audible pages often hide cash prices or show credit-based buying options. If you provide a local Audible auth token, the skill can check member-visible cash prices for matched titles and produce a more useful Want-to-Read discount report.\n\nWith all three pieces, the skill can help keep track of:\n\n- today's Audible promotion\n- whether the book is already in your Goodreads library\n- whether it is on your Want-to-Read shelf\n- whether it looks like a good fit for your taste\n- which Want-to-Read books are available on Audible\n- which matched titles appear discounted or priced below list\n- which deals are worth looking at first\n\nIf you are looking at this repository on GitHub, you are looking at the **source for a publishable ClawHub skill**, not a generic Python app or a standalone website.\n\nIf you want to re-implement the workflow without using the shipped skill directly, see [PROMPT_REQUEST.md](PROMPT_REQUEST.md). It captures the intention, scope, design guardrails, edge cases, and example prompt in one place.\n\n## Install or publish\n\nIf you just want to use it in OpenClaw once it is published:\n\n```bash\nopenclaw skills install audible-goodreads-deal-scout\n```\n\nStart a new OpenClaw session after install or after changing skill config so the fresh skill snapshot is picked up cleanly.\n\nIf you want to publish your own version from this repo:\n\n```bash\nclawhub login\nclawhub publish . \\\n  --slug audible-goodreads-deal-scout \\\n  --name \"Audible Goodreads Deal Scout\" \\\n  --version 0.1.16 \\\n  --changelog \"Reconcile cron timezone and configured delivery routing.\" \\\n  --tags latest\n```\n\n## 5-minute setup\n\nIf you want one straightforward setup path, use this:\n\n1. Pick your Audible store. If you do nothing, it defaults to `us`.\n2. Export your Goodreads library CSV if you want personalization.\n3. Optionally create a short notes file with what you like and dislike.\n4. Run:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh setup\n```\n\nThe setup response includes `nextSteps` with ready-to-run commands for `doctor`, checking the daily deal, scanning Want-to-Read books when a CSV is configured, and optional Audible auth.\n\nBy default, the skill writes its config, state, and artifacts under `.audible-goodreads-deal-scout/` in the active OpenClaw workspace.\n\nThat storage lives in the workspace, not inside `skills/audible-goodreads-deal-scout/`, because `openclaw skills install` and `openclaw skills update --force` can replace the installed skill folder.\n\nOnly point `goodreadsCsvPath`, `notesFile`, `configPath`, and `stateFile` at files or directories you actually want this skill to read or write.\n\n5. Then evaluate the current deal:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh prepare \\\n  --config-path .audible-goodreads-deal-scout/config.json\n```\n\n## How to get your Goodreads CSV\n\nIf you use Goodreads, the skill gets much stronger when you export your library.\n\nThe usual path is:\n1. Open `My Books`\n2. Open `Import and Export`\n3. Choose `Export Library`\n4. Wait for Goodreads to generate the file\n5. Download the CSV and point the skill at it with `goodreadsCsvPath`\n\nWhy the CSV matters:\n- it tells the skill what you already marked as `read`\n- it tells the skill what is already on your `to-read` shelf\n- it gives the fit step access to your ratings and written reviews\n\nIf your export is old, the skill will warn you, but it can still run.\n\n## If you do not use Goodreads\n\nThat is still a valid setup.\n\nYou can use a notes-only workflow:\n- no Goodreads CSV\n- one strong text file about your taste\n\nThe better the notes, the better the fit paragraph.\n\nGood notes usually include:\n- 5 to 15 books or authors you genuinely liked\n- a few examples of books you disliked and why\n- genres you seek out\n- genres you avoid\n- pacing preferences\n- tone preferences\n- what feels too sentimental, too slow, too commercial, too dark, too clever, too flat, and so on\n\nA strong notes file sounds like you talking to a smart bookseller, not like metadata.\n\nUseful:\n\n```md\nI like morally serious fiction, political tension, and books with ideas.\nI often like Orwell, Ishiguro, Le Guin, Vonnegut, and literary sci-fi.\nI lose interest when a book gets too sentimental or too plot-mechanical.\nI like books that are sharp, unsparing, and a bit strange, but still readable.\n```\n\nToo weak:\n\n```md\nI like good books.\n```\n\nIf you do not have Goodreads, the best setup is:\n- a thoughtful notes file\n- the default public Goodreads check\n- `deliveryPolicy: positive_only`\n\n## How the recommendation works\n\nAt a high level:\n- the skill fetches the current Audible daily promotion\n- it resolves the matching Goodreads page and public rating\n- it applies your Goodreads shelf rules if you provided a CSV\n- it uses your notes and/or Goodreads history to shape the fit paragraph\n- it decides whether to deliver the result based on your delivery policy\n\n### The default Goodreads threshold\n\nThe default threshold is `3.8`.\n\nThat means:\n- a public Goodreads average rating of `3.80` or lower is treated as below your quality cutoff\n- a rating above `3.8` is eligible\n\nThis is the **public Goodreads average**, not your own rating.\n\nGood starting points:\n- `4.0` if you want to be stricter\n- `3.8` if you want a balanced default\n- `3.6` or `3.7` if you want more titles to pass through\n\n### Goodreads shelf rules\n\nIf you provide a Goodreads CSV:\n- `read` => suppress\n- `currently-reading` => suppress\n- `to-read` => recommend immediately\n\nThat `to-read` override is intentional. If you already saved the book for later, that is treated as a strong positive signal and it can override the public Goodreads threshold.\n\n## Scan your Want-to-Read shelf for Audible discounts\n\nIf you configured a Goodreads CSV, you can also run a manual audit of books on your Goodreads `to-read` shelf:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh scan-want-to-read \\\n  --config-path .audible-goodreads-deal-scout/config.json \\\n  --limit 40 \\\n  --offset 0 \\\n  --progress plain\n```\n\nThis is intentionally an on-demand scan, not a scheduled monitor. It helps answer: \"Which books I already want to read appear to have a visible Audible discount right now?\"\n\nDefault behavior:\n- scans Audible US only in this first version\n- reads the current Goodreads CSV fresh each run\n- searches the first Audible result page for each selected Goodreads book\n- inspects the first three Audible result cards\n- fetches a product page only when the search card already shows plausible numeric discount evidence\n- prints compact Markdown to stdout\n- writes scan progress to stderr by default, so long runs can be monitored without corrupting Markdown/JSON output\n- keeps non-deals out of the default Markdown so the useful deals stay visible\n- suppresses duplicate Audible product matches in the final report while preserving scanned-row counts\n\nUseful batching pattern for larger shelves:\n\n```bash\n# Day 1\nsh ./scripts/audible-goodreads-deal-scout.sh scan-want-to-read \\\n  --config-path .audible-goodreads-deal-scout/config.json \\\n  --scan-order newest \\\n  --limit 40 \\\n  --offset 0\n\n# Day 2\nsh ./scripts/audible-goodreads-deal-scout.sh scan-want-to-read \\\n  --config-path .audible-goodreads-deal-scout/config.json \\\n  --scan-order newest \\\n  --limit 40 \\\n  --offset 40\n```\n\nUseful output flags:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh scan-want-to-read \\\n  --config-path .audible-goodreads-deal-scout/config.json \\\n  --output-json .audible-goodreads-deal-scout/reports/want-to-read.json \\\n  --output-md .audible-goodreads-deal-scout/reports/want-to-read.md \\\n  --include-non-deals\n```\n\nThe scan is deliberately conservative. If Audible hides cash pricing behind credits, membership language, or extra buying-choice UI, the result is marked as hidden or unknown instead of guessing. If a title or author match is ambiguous, it is marked for review instead of being treated as a deal.\n\nThe Markdown report shows whether authenticated pricing was enabled, live request usage, cache hits/writes, and a suggested next `--offset` command when more selected Want-to-Read books remain.\n\nPricing fields now separate two ideas:\n- `priceBasis` says where the price came from, for example `audible_public_cash` or `audible_member_cash`.\n- `dealType` says what kind of opportunity it appears to be, for example `limited_time_sale`, `member_cash_below_list`, or `cash_price_below_list`.\n\nGoodreads ratings:\n- If your Goodreads CSV includes an average-rating column, the scan uses it for ranking.\n- If the CSV does not include that column, the scan can enrich up to 20 discounted results from public Goodreads book pages when the CSV has Goodreads book ids.\n- Use `--no-goodreads-rating-enrichment` if you want to avoid those public Goodreads rating lookups.\n- Use `--goodreads-rating-limit N` to adjust the enrichment cap.\n\nProgress output:\n- `--progress plain` writes human-readable progress lines to stderr. This is the default CLI behavior.\n- `--progress json` writes JSONL progress events to stderr for agents and log processors.\n- `--progress none` disables progress output.\n- `--progress-interval 5` controls the minimum seconds between item progress updates. Start, stop, and completion events are always emitted when progress is enabled.\n\nFor long OpenClaw-agent runs, prefer `--progress json` plus `--output-json` and `--output-md`. Progress goes to stderr, while the report files stay stable and can be read after the command finishes or stops early.\n\n### Optional authenticated Audible price lookup\n\nAnonymous Audible pages often hide cash prices. If you want the Want-to-Read scan to check member-visible pricing on a headless OpenClaw machine, you can create a local Audible auth file through an external-browser flow.\n\nThis does **not** put your Audible password in the skill config. The flow prints an Amazon login URL, you open it on another device, complete login there, and paste the final redirect URL back into the CLI.\n\nThe resulting auth file is powerful local state: the flow requests cookie-style Audible/Amazon credential types for compatibility, then persists the bearer access/refresh token fields needed for token refresh and member-visible product-price lookup. The skill confines authenticated use to token refresh plus validated Audible product-price lookups on allowlisted API hosts, and `audible-auth-status` reports readiness without printing token contents.\n\nStart auth:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh audible-auth-start \\\n  --auth-path .audible-goodreads-deal-scout/audible-auth.json \\\n  --audible-marketplace us\n```\n\nOpen the printed `loginUrl` in your own browser. After login, Amazon will land on an error or not-found page; copy that final address-bar URL and finish auth:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh audible-auth-finish \\\n  --auth-path .audible-goodreads-deal-scout/audible-auth.json \\\n  --redirect-url \"<final-amazon-redirect-url>\"\n```\n\nThen scan with authenticated price lookup:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh scan-want-to-read \\\n  --config-path .audible-goodreads-deal-scout/config.json \\\n  --audible-auth-path .audible-goodreads-deal-scout/audible-auth.json \\\n  --limit 40 \\\n  --max-requests 90\n```\n\nYou can also save the auth path in `config.json` as `audibleAuthPath`, or set it during scripted setup with `--audible-auth-path`.\n\nAuthenticated scans usually spend one search request plus one authenticated price request for each matched Audible title. Use a higher `--max-requests` value than you would for anonymous scans. The authenticated price parser treats cash prices as the source of truth and ignores Audible credit prices such as `credit_price`.\n\nAuthenticated `discounted` means Audible returned a member-visible cash price below its list price for the product. It does not always prove a limited-time sale; check `dealType` in JSON if you need to distinguish `member_cash_below_list` from `limited_time_sale`.\n\nYou can test one known Audible ASIN first:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh audible-auth-test-price \\\n  --auth-path .audible-goodreads-deal-scout/audible-auth.json \\\n  --asin B08V8B2CGV\n```\n\nThe test response should include `pricingStatus`, `currentPrice`, `listPrice`, and `discountPercent` when Audible returns visible member cash pricing for that ASIN.\n\nCheck auth readiness and file permissions without printing tokens:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh audible-auth-status \\\n  --auth-path .audible-goodreads-deal-scout/audible-auth.json\n```\n\nIf the status reports broad file permissions on a local POSIX host, tighten them with:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh audible-auth-status \\\n  --auth-path .audible-goodreads-deal-scout/audible-auth.json \\\n  --fix-permissions\n```\n\nThe auth file is sensitive. Keep it under `.audible-goodreads-deal-scout/` in your OpenClaw workspace, do not commit it, do not paste it into chat, and remove it if you no longer want the skill to have authenticated Audible API access.\n\n## Supported marketplaces\n\nSupported and fixture-tested marketplace keys:\n- `us`\n- `uk`\n- `de`\n- `ca`\n- `au`\n\nIf you do nothing, the default is `us`.\n\nSupport here means the repo has fixture-backed coverage for:\n- daily-promotion detection\n- promotional price extraction\n- book identity extraction\n\nLive marketplace behavior can still vary. A supported store may still return:\n- no active promotion\n- a blocked page\n- a page-layout drift error\n\nDaily-promotion fetches use `audibleFetchBackend: \"auto\"` by default. That means the skill tries the built-in Python fetch path first and falls back to browser-like `curl` when Audible rejects the Python client with recoverable HTTP failures such as `503`. Use `\"python\"` or `\"curl\"` only when you deliberately want to force one backend.\n\nThe Want-to-Read discount scan is currently US-only. The daily-promotion workflow remains fixture-tested for the marketplace keys listed above.\n\nIf you want a non-US store, set `audibleMarketplace` to one of the keys above:\n\n```json\n{\n  \"audibleMarketplace\": \"uk\",\n  \"audibleFetchBackend\": \"auto\"\n}\n```\n\n## Privacy and data use\n\nThis part should be explicit.\n\n- The Python prep layer reads your Goodreads CSV locally.\n- The Python prep layer also reads your notes file locally.\n- The skill will read whatever file paths you configure, so keep those paths limited to the files you intend it to use.\n- The model step may use fit-context data unless you set `privacyMode` to `minimal`.\n- In `privacyMode: \"minimal\"`, the skill still uses local shelf logic, but it does **not** pass your personal CSV or notes content into the model fit step.\n- Delivery targets are whatever you configure in your own OpenClaw runtime.\n\nIf you want the safest default for personal data sharing, use:\n\n```json\n{\n  \"privacyMode\": \"minimal\"\n}\n```\n\n## What a notes file should look like\n\nIt does **not** need strict structure. A short, honest, messy note is fine.\n\nExample file: `examples/preferences.example.md`\n\nGood notes usually include:\n- books or authors you reliably like\n- genres or tones you usually avoid\n- pacing preferences\n- whether you like literary, commercial, cerebral, emotional, satirical, dark, warm, and so on\n\nWeak notes are still accepted, but they produce weaker fit output. For example, `I like good books` is valid input, but not very useful evidence.\n\n## Delivery policies\n\n`deliveryPolicy` controls how noisy the skill is:\n\n| Policy | Best for | Behavior |\n| --- | --- | --- |\n| `positive_only` | most people | send only likely fits |\n| `summary_on_non_match` | people who want visibility into skips | send full recommendations, but short summary cards for suppressions/errors |\n| `always_full` | logging and audits | send every final result in full |\n\nRecommended default:\n- `positive_only`\n\nThat gives the best signal-to-noise ratio for most users.\n\n## Telegram, WhatsApp, and other channels\n\nThis repository does **not** ship its own Telegram or WhatsApp connector.\n\nInstead, it uses the OpenClaw message surface:\n- `openclaw message send --channel ... --target ...`\n\nThat means delivery works whenever your OpenClaw environment already has a supported channel configured.\n\n### Telegram\n\nIf your OpenClaw setup supports Telegram delivery, configure:\n\n```json\n{\n  \"deliveryChannel\": \"telegram\",\n  \"deliveryTarget\": \"-1000000000000\"\n}\n```\n\n`deliveryTarget` is the Telegram chat or channel id you want to post into.\n\n### WhatsApp\n\nWhatsApp can work **only if** your OpenClaw install already exposes a WhatsApp-capable message channel.\n\nIn that case the pattern is the same:\n\n```json\n{\n  \"deliveryChannel\": \"whatsapp\",\n  \"deliveryTarget\": \"<your-whatsapp-target>\"\n}\n```\n\nThis repo does not create that WhatsApp channel. It only uses it if your OpenClaw runtime already provides it.\n\n## What the output looks like\n\n### Positive recommendation\n\n```text\nAudible US Daily Promotion — 2026-04-20\n\n𝗦𝗹𝗮𝘂𝗴𝗵𝘁𝗲𝗿𝗵𝗼𝘂𝘀𝗲-𝗙𝗶𝘃𝗲 — Kurt Vonnegut (2015)\nPrice: $1.99 (-87%, list price $14.95)\nGoodreads rating: 4.11 (1,364,737 ratings)\nLength: 5:13 hrs\nGenre: Literature & Fiction, Thought-Provoking, Fiction, Witty\n\nSlaughterhouse-Five is the now famous parable of Billy Pilgrim...\n\nFit: Strong match, on your to-read shelf. You tend to respond well to fiction that is intellectually playful, structurally bold, and willing to smuggle serious ideas through wit. The main risk is that Vonnegut's emotional distance and satirical flatness may leave you admiring it more than fully feeling it.\n\nAudible: https://www.audible.com/pd/...\nGoodreads: https://www.goodreads.com/book/show/...\n```\n\n### Short non-match summary\n\n```text\nAudible US Daily Promotion — 2026-04-20\n\n𝗦𝗹𝗮𝘂𝗴𝗵𝘁𝗲𝗿𝗵𝗼𝘂𝘀𝗲-𝗙𝗶𝘃𝗲 — Kurt Vonnegut (2015)\n\nFit: You marked it as read on Goodreads.\n\nAudible: https://www.audible.com/pd/...\n```\n\n## One complete walkthrough\n\nIf you want to see the whole flow once from start to finish, this is the cleanest path.\n\n1. Write a config and optional notes/delivery settings:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh setup \\\n  --non-interactive \\\n  --config-path .audible-goodreads-deal-scout/config.json \\\n  --audible-marketplace us \\\n  --audible-auth-path .audible-goodreads-deal-scout/audible-auth.json \\\n  --threshold 3.8 \\\n  --goodreads-csv \"/absolute/path/to/goodreads_library_export.csv\" \\\n  --notes-file \"/absolute/path/to/preferences.md\" \\\n  --delivery-channel telegram \\\n  --delivery-target \"-1000000000000\" \\\n  --delivery-policy positive_only\n```\n\n2. Prepare today's deal:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh prepare \\\n  --config-path .audible-goodreads-deal-scout/config.json\n```\n\nThat always writes the current prep result to `.audible-goodreads-deal-scout/artifacts/current/prepare-result.json`, including error or suppress outcomes. Ready outcomes also include:\n- `runtime-input.json`\n- `runtime-prompt.md`\n- `runtime-output-schema.json`\n\n3. Let the OpenClaw runtime produce a `runtime-output.json` file that matches the schema from step 2. A typical successful output looks like:\n\n```json\n{\n  \"schemaVersion\": 1,\n  \"goodreads\": {\n    \"status\": \"resolved\",\n    \"url\": \"https://www.goodreads.com/book/show/1\",\n    \"title\": \"Signal Fire\",\n    \"author\": \"Jane Story\",\n    \"averageRating\": 4.15,\n    \"ratingsCount\": 9501\n  },\n  \"fit\": {\n    \"status\": \"written\",\n    \"sentence\": \"Fit: Likely to work if you want sharp, idea-driven speculative fiction. The main risk is that it may feel more cerebral than emotionally warm.\"\n  }\n}\n```\n\n4. Finalize the public result contract:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh finalize \\\n  --prepare-json .audible-goodreads-deal-scout/artifacts/current/prepare-result.json \\\n  --runtime-output /tmp/runtime-output.json\n```\n\n5. If you configured delivery, send the finished message:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh run-and-deliver \\\n  --config-path .audible-goodreads-deal-scout/config.json \\\n  --prepare-json .audible-goodreads-deal-scout/artifacts/current/prepare-result.json \\\n  --runtime-output /tmp/runtime-output.json\n```\n\nIf you just want to inspect the decision locally, stop after `finalize`.\n\n## Troubleshooting\n\nThree issues cause most confusing runs:\n\n- Wrong notes path: if `notesFile` or `preferencesPath` points at a missing file, the prep step now returns `error_missing_notes_file` instead of silently continuing.\n- Wrong CSV header override: `--csv-column role=Header` must match the Goodreads export header exactly. If you are unsure, run `show-csv-headers` first.\n- Stale Goodreads export: if the CSV is old, the skill can still run, but read status, shelf state, and fit evidence may lag behind your actual library.\n- Stale scheduled artifact: scheduled `run-and-deliver` refuses error prep results and stale `prepare-result.json` files whose `metadata.storeLocalDate` no longer matches the current Audible marketplace date.\n- Stale downstream artifacts: every fresh `prepare` removes old `runtime-output.json`, `run-and-deliver-result.json`, and `mark-emitted-result.json` from the current artifact directory before writing the new prep result.\n- Transient Audible daily-deal pages: the prep step retries transient fetch failures and temporary no-active-promotion parses before returning a suppression or error. With `audibleFetchBackend: \"auto\"`, it can recover from Python-client rejections by retrying the same URL through browser-like `curl`.\n\nUseful checks:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh doctor --config-path .audible-goodreads-deal-scout/config.json\nsh ./scripts/audible-goodreads-deal-scout.sh show-csv-headers \"/absolute/path/to/goodreads_library_export.csv\"\nsh ./scripts/audible-goodreads-deal-scout.sh publish-audit --version 0.1.16 --tags latest\n```\n\n`doctor` checks the configured config, CSV, notes, auth file, cache directory, delivery settings, cron settings, Audible fetch backend, local OpenClaw binary, bundled shell wrapper, and installed skill version. Add `--check-cron` when you want it to query live OpenClaw cron jobs; disabled related jobs are reported separately from missing jobs.\n\nAdd `--check-audible-fetch` when you want a live daily-deal fetch probe from the current host. This is opt-in because it makes a network request to Audible.\n\nIf your OpenClaw install strips executable bits from bundled scripts, run the wrapper through `sh` exactly as shown above and in `SKILL.md`.\n- Scheduled runs cannot stop for interactive exec approval. Before enabling daily automation, verify that both OpenClaw exec policy and the Codex app-server policy allow unattended cron commands on your trusted host. If the Codex app-server keeps asking for command approval, set its trusted local policy explicitly, for example `plugins.entries.codex.config.appServer.approvalPolicy: \"never\"` with `sandbox: \"danger-full-access\"`, or use an equivalent narrow allowlist for the shell command your host actually runs.\n- Before enabling `dailyAutomation` or `--register-cron`, confirm the configured delivery channel and target are the ones you actually want the skill to use through your local OpenClaw runtime.\n\n## Advanced CLI usage\n\nIf you prefer scripted setup instead of interactive setup:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh setup \\\n  --non-interactive \\\n  --config-path .audible-goodreads-deal-scout/config.json \\\n  --audible-marketplace us \\\n  --threshold 3.8 \\\n  --goodreads-csv \"/absolute/path/to/goodreads_library_export.csv\" \\\n  --notes-file \"/absolute/path/to/preferences.md\" \\\n  --delivery-channel telegram \\\n  --delivery-target \"-1000000000000\" \\\n  --delivery-policy positive_only\n```\n\nUseful helper commands:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh doctor --config-path .audible-goodreads-deal-scout/config.json\nsh ./scripts/audible-goodreads-deal-scout.sh show-csv-headers \"/absolute/path/to/goodreads_library_export.csv\"\nsh ./scripts/audible-goodreads-deal-scout.sh measure-context --goodreads-csv \"/absolute/path/to/goodreads_library_export.csv\" --output /tmp/fit-context.json\nsh ./scripts/audible-goodreads-deal-scout.sh publish-audit --version 0.1.16\n```\n\nFinalize and deliver in one step:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh run-and-deliver \\\n  --config-path .audible-goodreads-deal-scout/config.json \\\n  --prepare-json .audible-goodreads-deal-scout/artifacts/current/prepare-result.json \\\n  --runtime-output /tmp/runtime-output.json\n```\n\n## Repository structure\n\n- `SKILL.md`: agent-facing runtime instructions\n- `TRUST.md`: security, data-access, and no-purchase behavior summary\n- `agents/openai.yaml`: interface metadata and default prompt for OpenClaw agent surfaces\n- `scripts/audible-goodreads-deal-scout.sh`: bundled shell wrapper for local CLI and OpenClaw installs that may not preserve executable bits\n- `audible_goodreads_deal_scout/core.py`: prep/orchestration logic\n- `audible_goodreads_deal_scout/audible_fetch.py`: guarded Audible HTTP fetching, browser-like headers, and curl fallback\n- `audible_goodreads_deal_scout/audible_auth.py`: optional headless Audible auth and API price lookup helpers\n- `audible_goodreads_deal_scout/audible_catalog.py`: Audible catalog search and conservative price parsing\n- `audible_goodreads_deal_scout/cli_errors.py`: structured CLI error payload helpers\n- `audible_goodreads_deal_scout/diagnostics.py`: local doctor/status checks\n- `audible_goodreads_deal_scout/goodreads_rating.py`: optional public Goodreads rating enrichment for Want-to-Read reports\n- `audible_goodreads_deal_scout/want_to_read_scan.py`: Goodreads Want-to-Read scan orchestration and report rendering\n- `audible_goodreads_deal_scout/runtime_contract.py`: runtime input, prompt, schema, and prepare-result artifact writing\n- `audible_goodreads_deal_scout/rendering.py`: card rendering and delivery planning\n- `audible_goodreads_deal_scout/delivery.py`: config, cron, and delivery helpers\n- `audible_goodreads_deal_scout/public_cli.py`: setup and CLI entrypoint\n- `config.example.json`: public config example\n- `examples/preferences.example.md`: sample notes file\n- `docs/release-checklist.md`: release checklist for publishable builds\n\n## Publish to ClawHub\n\nBefore publishing, run:\n\n```bash\nsh ./scripts/audible-goodreads-deal-scout.sh publish-audit --version 0.1.16 --tags latest\n```\n\nFor public auditability, create a matching Git tag and GitHub release for each ClawHub version, for example `v0.1.16`.\n\n## Why this is worth publishing\n\nThe value is not just “show me today’s Audible promotion.”\n\nThe real value is:\n- filtering instead of promo noise\n- combining public quality with personal fit\n- respecting `read`, `currently-reading`, and `to-read`\n- optional proactive delivery into a real channel\n- graceful handling of suppressions and lookup failures\n\nFile v0.1.17:_meta.json\n\n{\n  \"ownerId\": \"kn74j40rqb6m5s0whvynrxcq098212ny\",\n  \"slug\": \"audible-goodreads-deal-scout\",\n  \"version\": \"0.1.17\",\n  \"publishedAt\": 1784493118493\n}\n\nFile v0.1.17:CHANGELOG.md\n\n# Changelog\n\n## 0.1.16\n\n- Route registered OpenClaw cron jobs through the configured delivery channel and target\n- Reconcile existing Audible cron jobs when their schedule, IANA timezone, message, or delivery route drifts\n- Make live cron diagnostics fail on active schedule or delivery mismatches\n\n## 0.1.15\n\n- Preserve existing config values when rerunning setup or registering cron from an existing config path\n- Prevent cron registration from accidentally dropping Goodreads CSV, delivery, auth, or CSV column settings when omitted from a follow-up setup command\n- Clarify that unattended OpenClaw/Codex cron runs need a non-interactive command-approval policy on trusted local hosts\n\n## 0.1.14\n\n- Resolve the OpenClaw CLI from common user install locations such as `~/.npm-global/bin/openclaw` when non-interactive PATHs omit it\n- Add a `version` command and include `skillVersion` in `doctor` output for installed-bundle checks\n- Improve live cron diagnostics so disabled related jobs are reported separately from missing jobs\n- Declare `sh` in skill requirements because the documented launcher uses the shell wrapper\n\n## 0.1.13\n\n- Keep optional cookie-style Audible auth registration for member-visible prices without persisting website/store cookie payloads\n- Add auth status metadata that explains the credential purpose and allowed use without exposing token contents\n- Expand trust and README guidance for optional Audible authentication, including refresh-token and cookie-style credential handling\n\n## 0.1.12\n\n- Restrict Audible fetches to known HTTPS Audible hosts and daily-deal/search/product paths before either Python or curl can request them\n- Add `doctor --check-audible-fetch` as an opt-in live host probe for the daily-deal fetch path\n- Extract browser-like Audible fetch backends into `audible_fetch.py` and remove the legacy contract harness in favor of the public CLI commands\n- Split shared test fixtures and Audible fetch tests out of the main test module\n\n## 0.1.11\n\n- Always write a fresh `artifacts/current/prepare-result.json` for ready, suppress, and error prepare outcomes so failed current-day prep cannot leave a stale deliverable artifact behind\n- Refuse scheduled `run-and-deliver` attempts for error prep results or stale scheduled artifacts whose `metadata.storeLocalDate` no longer matches the current Audible marketplace date\n- Make `mark-emitted` validate the delivered scheduled prepare artifact and mark only its current `metadata.dealKey`\n- Use browser-like Audible daily-promotion request headers, including `Accept-Language`, to reduce avoidable 503 responses\n\n## 0.1.10\n\n- Add `TRUST.md` with data-access, network, optional auth, privacy-mode, and no-purchase behavior documentation\n- Surface data-access and no-purchase disclosures in `SKILL.md` for the ClawHub-visible page\n- Align `SKILL.md` license metadata with ClawHub's MIT-0 skill license\n- Update release guidance to create matching Git tags and GitHub releases for ClawHub versions\n\n## 0.1.9\n\n- Add a human-facing ClawHub overview to `SKILL.md` so the marketplace README tab explains the skill before agent runtime instructions\n- Keep agent-facing operational instructions under a dedicated runtime section\n- Update release metadata defaults for the marketplace-rendering fix\n\n## 0.1.8\n\n- Refresh ClawHub README and release metadata\n\n## 0.1.7\n\n- Add stderr progress reporting for long Want-to-Read scans, including JSONL mode for OpenClaw agents and log processors\n- Suppress duplicate Audible product matches in final Want-to-Read reports while preserving scanned-row counts and duplicate metadata in JSON\n- Add scan report metadata for authenticated-pricing state, cache stats, request usage, and next-batch hints\n- Add `priceBasis` and `dealType` fields so reports can distinguish member cash prices below list from limited-time sale or promotion signals\n- Enrich missing Goodreads average ratings for a capped number of discounted Want-to-Read results by Goodreads book id\n- Retry transient daily-promotion fetch failures and temporary no-active-promotion parses before suppressing or erroring\n- Add setup `nextSteps` guidance and strengthen publish-audit checks for generated/private artifact exclusions\n- Clarify that authenticated `discounted` means member-visible cash price below list price, not guaranteed limited-time sale status\n- Improve release and troubleshooting docs for long scans, authenticated price lookup, and local readiness checks\n- Reduce duplicated scan-progress bookkeeping in the Want-to-Read scan implementation\n\n## 0.1.5\n\n- Add stdlib-only headless Audible external-login auth helpers for optional authenticated price lookup\n- Add authenticated Audible catalog product pricing lookup for matched Want-to-Read scan results\n- Add `--audible-auth-path` to `scan-want-to-read` and helper commands for auth start, finish, and one-ASIN price testing\n- Add `doctor` and `audible-auth-status` commands for local readiness, auth expiry, and file-permission checks\n- Add structured CLI error payloads with token redaction for command failures\n- Ignore Audible credit prices when classifying authenticated cash discounts\n- Clarify external-browser auth instructions and authenticated request budgeting\n- Move prepare-result artifact writing behind the runtime contract module boundary\n- Keep auth files out of published bundles and document that the auth file is sensitive local state\n\n## 0.1.4\n\n- Add a manual `scan-want-to-read` command for checking Goodreads `to-read` books against visible Audible US numeric discounts\n- Add conservative Audible catalog search, pricing parsing, parsed-result cache, request budgeting, and block-like circuit breaker handling for the new scan\n- Add compact Markdown and structured JSON reports for Want-to-Read discount scans\n- Add offline fixture coverage for scan selection, matching, pricing, request budget behavior, cached block failures, and compact report output\n\n## 0.1.3\n\n- Invoke the published shell wrapper through `sh` in `SKILL.md` and README examples so official OpenClaw installs still work even when the installed script loses its executable bit\n- Clarify that default config, state, and artifact storage belongs under `.audible-goodreads-deal-scout/` in the active OpenClaw workspace, not inside the installed skill folder or under the legacy `.audible-goodreads-deal` name\n- Clarify in the README that configured CSV, notes, config, and state paths should only point at files the user intends the skill to read or write\n- Add README guidance to review delivery settings before enabling daily automation or cron registration\n- Soften transaction-heavy README wording for a skill that evaluates promotions rather than making purchases\n- Add a release-check step to verify the live ClawHub license summary matches `SKILL.md` and `LICENSE.txt`\n\n## 0.1.2\n\n- Rename the published shell wrapper to `scripts/audible-goodreads-deal-scout.sh` so the ClawHub bundle exposes the documented entrypoint\n- Rename the repository license file to `LICENSE.txt` and require it in the publish audit so extensionless files do not disappear from published bundles\n- Update release guidance to verify the published wrapper and license files after upload\n\n## 0.1.1\n\n- Move the published wrapper entrypoint from `bin/` to `scripts/` so the package layout matches ClawHub skill conventions\n- Update SKILL and README command examples to use the published `scripts/audible-goodreads-deal-scout` wrapper path\n- Add release guidance to verify the published file manifest after upload\n\n## 0.1.0\n\n- Initial public release candidate for `audible-goodreads-deal-scout`\n- Audible daily-promotion evaluation with Goodreads public score\n- Optional Goodreads CSV shelf logic\n- Optional freeform taste notes\n- Delivery policy support for positive-only, full, and summary delivery\n- Publish-time privacy audit\n- Marketplace certification fixtures and runtime-contract tests\n\nFile v0.1.17:examples/preferences.example.md\n\nI usually like fiction that is idea-driven, formally interesting, and emotionally controlled rather than sentimental.\n\nAuthors and books I tend to like:\n- Ursula K. Le Guin\n- George Orwell\n- Kazuo Ishiguro\n- David Mitchell\n- literary science fiction\n- political satire\n- speculative fiction with philosophical weight\n\nWhat I usually do not like:\n- generic airport thrillers\n- fantasy that is mostly lore and worldbuilding\n- romance-forward plots\n- books that rely on shock value more than ideas\n\nWhen in doubt, I prefer:\n- originality over comfort\n- structure and voice over plot mechanics\n- books that leave something to think about afterward\n\nFile v0.1.17:PROMPT_REQUEST.md\n\n# Prompt Request\n\nUse this file if you want to re-implement Audible Goodreads Deal Scout without using this repository's code directly.\n\nThe first sections are for humans: what the skill is trying to do and why it exists. The later sections are for a coding agent: contracts, edge cases, implementation boundaries, and acceptance criteria.\n\n## Human Intention\n\nBuild a small, selective reading-deal workflow.\n\nThe workflow should help a reader notice the few Audible deals that are actually worth attention because they clear a public quality bar, match the reader's Goodreads library or Want-to-Read shelf, or fit the reader's stated taste.\n\nIt should not feel like a deal feed. It should feel like a careful filter: fewer notifications, better relevance, and clear reasons.\n\nThe product posture is important:\n- The system reports opportunities only.\n- It does not buy, reserve, check out, redeem credits, manage subscriptions, or complete purchases.\n- Any purchase decision stays manual and outside the workflow.\n\n## Human Scope\n\nThe workflow should support three related jobs:\n\n1. Daily deal check:\n   Fetch today's Audible daily promotion, compare it with Goodreads and optional personal context, then recommend, suppress, or report an error.\n2. Want-to-Read discount scan:\n   Use a Goodreads CSV to scan books on the user's Want-to-Read shelf against Audible US and report visible discounts or member-visible cash prices when optional Audible auth is configured.\n3. Setup and diagnostics:\n   Help a user create config, verify local paths, check auth readiness, inspect CSV headers, and understand what data the workflow reads or writes.\n\nThe workflow should not:\n- Become a general Audible scraper.\n- Build account-login browser automation.\n- Auto-buy anything.\n- Store mutable state inside the installed skill folder.\n- Depend on private infrastructure, local machine names, tunnel names, or unpublished credentials.\n\n## Best User Setup\n\nThe workflow works with public data only, but the best setup uses:\n\n- The official Goodreads library CSV export.\n- Short taste notes, written or dictated by the user, or drafted by an AI from favorite books, disliked books, preferred genres, pacing, tone, and themes.\n- Optional Audible authentication only when the user wants member-visible cash prices in Want-to-Read scans.\n\nIf the user does not want personalization, the daily deal flow should still work from public Goodreads data only.\n\n## Trust And Data Access\n\nMake data access explicit and narrow.\n\nThe workflow may read:\n- A config file.\n- A Goodreads CSV, only when configured.\n- A notes file or pasted notes, only when configured.\n- Audible daily deal, search, and product pages.\n- A local Audible auth file, only when the user explicitly creates and supplies one.\n- Goodreads public pages for public rating resolution and optional rating enrichment.\n- OpenClaw CLI state only for delivery, cron, and diagnostics.\n\nThe workflow may write:\n- Config, artifacts, reports, cache, and state under a workspace storage directory.\n- Optional delivery messages through a configured OpenClaw channel.\n- Optional cron entries when daily automation registration is requested.\n\nDefault storage should be:\n\n```text\n<workspace>/.audible-goodreads-deal-scout/\n```\n\nDo not store mutable config, cache, auth, state, or artifacts under the installed skill directory, because skill updates may replace that folder.\n\n## Implementation Model\n\nImplement this as a ClawHub / OpenClaw skill-style staged workflow, not as one monolithic prompt.\n\nThe daily deal path has four stages:\n\n1. Prepare:\n   Fetch and parse Audible deterministically, load optional local inputs, apply local short-circuit rules, and write artifacts.\n2. Runtime:\n   Let the agent resolve Goodreads public evidence and write compact fit text. Return JSON only.\n3. Finalize:\n   Validate runtime JSON, apply decision rules, and render the final message.\n4. Optional delivery:\n   Apply delivery policy, send through OpenClaw if requested, and mark scheduled emissions safely.\n\nThe Want-to-Read scan is a separate manual command:\n\n1. Load Goodreads CSV.\n2. Select current `to-read` rows.\n3. Search Audible conservatively.\n4. Parse visible prices or optional authenticated prices.\n5. Render compact Markdown and structured JSON.\n\nThe core design choice is deterministic first, model second. The model should not scrape Audible or decide control flow that can be handled locally.\n\n## Required Inputs\n\nMinimum daily deal inputs:\n- Audible marketplace, default `us`.\n- Goodreads score threshold, default `3.8`.\n\nOptional daily deal inputs:\n- Goodreads CSV path.\n- Notes file or inline notes.\n- Privacy mode: `normal` or `minimal`.\n- Invocation mode: `manual` or `scheduled`.\n- State file for duplicate scheduled suppression.\n- Artifact directory.\n- Delivery policy.\n- Delivery channel and target.\n\nMinimum Want-to-Read scan inputs:\n- Goodreads CSV path with `to-read` shelf data.\n- Audible marketplace `us` for v1.\n\nOptional Want-to-Read scan inputs:\n- `--limit N`\n- `--offset N`\n- `--scan-order newest|csv|oldest|random`\n- `--seed TEXT`\n- `--max-requests N`\n- `--request-delay SECONDS`\n- `--min-discount-percent N`\n- `--output-json PATH`\n- `--output-md PATH`\n- `--include-non-deals`\n- `--verbose`\n- `--progress plain|json|none`\n- `--progress-interval SECONDS`\n- `--refresh-cache`\n- `--no-cache`\n- `--offline-fixtures PATH`\n- `--title TEXT --author TEXT` for a single-book debug scan\n- `--audible-auth-path PATH` for optional authenticated price lookup\n\n## Daily Deal Prepare Rules\n\nApply these rules in order:\n\n1. Resolve config and storage paths.\n2. Validate the Audible marketplace.\n3. Resolve notes text. If a configured notes file is missing, return `error_missing_notes_file`.\n4. Validate the configured Goodreads CSV path. If explicitly configured and missing, return `error_missing_csv`.\n5. Fetch the current Audible daily promotion with browser-like headers:\n   - a normal browser User-Agent\n   - `Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8`\n   - `Accept-Encoding: gzip, deflate`\n   - `Accept-Language: en-US,en;q=0.9`\n6. Guard unauthenticated Audible fetches before network access: allow only HTTPS Audible daily-deal, search, and product URLs on known Audible marketplace hosts unless a deliberate debug override is used.\n7. Use an `auto` fetch backend by default: try the Python fetch path first, then fall back to browser-like `curl` for recoverable Audible HTTP failures such as Python-client `503`, `403`, `429`, or gateway errors. Preserve diagnostics including backend, HTTP status, final URL, attempts, and fallback reason in prepare metadata.\n8. Retry transient daily-promotion failures and temporary no-active-promotion parses before returning a suppression or error.\n9. Parse title, author, product id, URL, summary, genres, runtime, year, sale price, list price, and hidden/member-price signals where visible.\n10. Compute a deal key from marketplace, store-local date, and product id.\n11. In scheduled mode, suppress a duplicate if the same deal key was already emitted.\n12. Load Goodreads CSV if configured.\n13. Validate CSV column overrides against actual detected headers before parsing.\n14. Classify exact shelf matches locally.\n15. If matching is ambiguous for the same title, return `error_ambiguous_personal_match`.\n16. If exact shelf is `read`, return `suppress_already_read`.\n17. If exact shelf is `currently-reading`, return `suppress_currently_reading`.\n18. If exact shelf is `to-read`, keep the run active. This is positive evidence and can override the public Goodreads threshold later.\n19. Build compact personal artifacts only when privacy allows it.\n20. Always write a fresh `prepare-result.json`, including `ready`, `suppress`, and `error` outcomes.\n\nThe last rule is critical. A failed current-day prepare must never leave a stale previous-day `artifacts/current/prepare-result.json` behind. A fresh prepare must also remove stale downstream current artifacts, including `runtime-output.json`, `run-and-deliver-result.json`, and `mark-emitted-result.json`, so old delivery results are not visible as current.\n\n## Daily Deal Runtime Contract\n\nThe runtime step must read prepared artifacts and return JSON only:\n\n```json\n{\n  \"schemaVersion\": 1,\n  \"goodreads\": {\n    \"status\": \"resolved | no_match | lookup_failed\",\n    \"url\": \"string | null\",\n    \"title\": \"string | null\",\n    \"author\": \"string | null\",\n    \"averageRating\": \"number | null\",\n    \"ratingsCount\": \"integer | null\",\n    \"evidence\": \"string | null\"\n  },\n  \"fit\": {\n    \"status\": \"written | not_applicable | unavailable\",\n    \"sentence\": \"string | null\"\n  }\n}\n```\n\nRuntime rules:\n- Prefer Goodreads book pages over author, list, review, or discussion pages.\n- Verify title and author before trusting a Goodreads score.\n- Use `lookup_failed` when Goodreads could not be checked.\n- Use `no_match` when Goodreads was checked but no confident matching book page was found.\n- If `privacyMode` is `minimal`, do not use raw CSV, detailed taste artifacts, review-source artifacts, or notes.\n- If fit text is written, make it compact: roughly 2 or 3 short sentences, about 45 to 90 words.\n- Mention one likely appeal and one credible limitation when useful.\n- Do not invent taste evidence.\n\n## Daily Deal Finalize Rules\n\nFinalize maps prepare/runtime data into one user-facing decision.\n\nFinal statuses:\n- `recommend`\n- `suppress`\n- `error`\n\nCore final reason codes:\n- `recommend_to_read_override`\n- `recommend_public_threshold`\n- `suppress_below_goodreads_threshold`\n- `suppress_no_goodreads_match`\n- `error_goodreads_lookup_failed`\n\nRules:\n1. If prepare returned `suppress` or `error`, finalize that result directly.\n2. If Goodreads status is `lookup_failed`, return an error.\n3. If Goodreads status is `no_match`, suppress.\n4. If exact shelf is `to-read`, recommend even if the public threshold is not met.\n5. Otherwise recommend only when Goodreads average rating is greater than the configured threshold.\n6. Suppress when Goodreads average rating is less than or equal to the threshold.\n7. If fit writing is unavailable, use a fallback fit line and keep the decision.\n\nKeep the final message concise and structured:\n- marketplace and store date\n- title, author, and year when known\n- price and discount when known\n- Goodreads rating and rating count when resolved\n- runtime and genre when known\n- short Audible description\n- fit paragraph or fallback fit line\n- Audible link\n- Goodreads link when available\n\n## Scheduled Delivery Safety\n\nScheduled runs need stricter safety than manual runs.\n\nRules:\n- `run-and-deliver` must refuse scheduled prepare results whose status is `error`.\n- `run-and-deliver` must refuse stale scheduled artifacts when `metadata.storeLocalDate` does not equal the current Audible marketplace date.\n- `mark-emitted` must mark only the deal key from the same current scheduled prepare artifact that was actually delivered.\n- Do not mark emitted from an arbitrary loose deal key unless it matches the current artifact.\n- Manual runs should not be blocked by duplicate scheduled state.\n\nThese rules prevent a failed current-day prepare from sending a stale previous-day recommendation.\n\n## Delivery Policies\n\nDelivery policy should be explicit:\n\n- `positive_only`: send only recommendations.\n- `always_full`: send the full message for recommend, suppress, and error results.\n- `summary_on_non_match`: send full recommendations and short summaries for suppress or error results.\n\nDelivery should use the user's configured OpenClaw channel and target. Do not assume Telegram, WhatsApp, or any specific target unless configured.\n\n## Privacy Modes\n\n`normal`:\n- The runtime may receive compact fit context, review-source context, and notes artifacts when configured.\n- Personal context should be used only for the fit paragraph and local shelf rules.\n\n`minimal`:\n- The prepare layer may use local shelf data for deterministic decisions.\n- Do not write or expose detailed personal fit artifacts to the runtime.\n- Do not expose raw notes or raw Goodreads review text to the runtime.\n- Runtime output should use public Goodreads evidence and summary metadata only.\n\nPrivacy must be enforced by data minimization, not just by prompt instructions.\n\n## Want-To-Read Scan Scope\n\nThe Want-to-Read scan is a manual audit, not continuous monitoring.\n\nIt should answer:\n\n```text\nAmong the Want-to-Read books I scan right now, which ones visibly look discounted on Audible?\n```\n\nV1 constraints:\n- US Audible marketplace only unless explicitly extended later.\n- No cron.\n- No delivery.\n- No long-lived \"already scanned forever\" state.\n- No account browser automation.\n- No hidden-price chasing through secondary buying-choice UI.\n- No product-page fetch unless a search card already shows plausible numeric discount evidence or visible current/list prices that need confirmation.\n- Use offset and limit for large backlogs instead of persistent scan progress state.\n\nRecommended backlog usage:\n\n```bash\nscan-want-to-read --scan-order newest --limit 40 --offset 0\nscan-want-to-read --scan-order newest --limit 40 --offset 40\nscan-want-to-read --scan-order newest --limit 40 --offset 80\n```\n\n## Want-To-Read Selection\n\nSelection rules:\n\n1. Load the Goodreads CSV.\n2. Resolve relevant headers with tolerant defaults and validated overrides.\n3. Filter rows whose effective shelf is `to-read`.\n4. Deduplicate within the current report by Goodreads book id when present, otherwise normalized title plus author.\n5. Sort by requested scan order:\n   - `newest`\n   - `oldest`\n   - `csv`\n   - `random`\n6. For random ordering, use a deterministic seed for the current invocation only.\n7. Apply offset.\n8. Scan up to limit.\n\nIf the CSV changes, simply re-read it on the next invocation. Do not require a strict CSV fingerprint for resume.\n\n## Want-To-Read Matching\n\nKeep matching conservative and deterministic.\n\nSearch:\n- One Audible search request per Goodreads book.\n- Search URL shape for US: `https://www.audible.com/search?keywords=<title author>`.\n- Parse only the first search page.\n- Inspect the first three result cards.\n- Try card 2 and card 3 if card 1 is unrelated.\n\nCandidate acceptance:\n- Accept exact normalized title match, or exact after subtitle/series stripping.\n- Require exact or strong partial visible author agreement.\n- Use Goodreads primary author as the main author.\n- Additional Goodreads authors may improve confidence but should not hide a primary author mismatch.\n- Missing search-card author should usually be `needs_review`, not an excuse for identity-only product fetch.\n\nDo not overbuild v1:\n- Do not solve all translated editions.\n- Do not auto-accept abridged, dramatized, omnibus, podcast, course, or adaptation variants without warnings.\n- Do not use narrator names as positive author evidence.\n- Do not treat ISBN as a guaranteed audiobook match; it is rare supporting evidence at most.\n\n## Want-To-Read Pricing\n\nStatuses:\n- `discounted`\n- `available_no_discount`\n- `price_hidden`\n- `price_unknown`\n- `needs_review`\n- `not_found`\n- `lookup_failed`\n\nPricing fields should include:\n- `currencyCode`\n- `currentPrice`\n- `listPrice`\n- `discountPercent`\n- `pricingStatus`\n- `priceBasis`\n- `dealType`\n\nDistinguish:\n- `dealType: limited_time_sale` or similar when there is a visible sale/promotion signal.\n- `dealType: member_cash_below_list` when authenticated member cash price is below list but not clearly a limited-time sale.\n- `priceBasis: audible_public_cash` for anonymous visible cash prices.\n- `priceBasis: audible_member_cash` for authenticated member-visible cash prices.\n- `priceBasis: unknown`\n\nArchive v0.1.16: 31 files, 107487 bytes\n\nFiles: agents/openai.yaml (317b), audible_goodreads_deal_scout/__init__.py (209b), audible_goodreads_deal_scout/audible_auth.py (24001b), audible_goodreads_deal_scout/audible_catalog.py (30928b), audible_goodreads_deal_scout/audible_fetch.py (18079b), audible_goodreads_deal_scout/audible_source.py (11790b), audible_goodreads_deal_scout/cli_errors.py (878b), audible_goodreads_deal_scout/constants.py (2361b), audible_goodreads_deal_scout/core.py (47046b), audible_goodreads_deal_scout/delivery.py (20103b), audible_goodreads_deal_scout/diagnostics.py (13820b), audible_goodreads_deal_scout/goodreads_csv.py (6509b), audible_goodreads_deal_scout/goodreads_rating.py (5119b), audible_goodreads_deal_scout/public_cli.py (31845b), audible_goodreads_deal_scout/rendering.py (8792b), audible_goodreads_deal_scout/repo_audit.py (1512b), audible_goodreads_deal_scout/runtime_contract.py (7829b), audible_goodreads_deal_scout/settings.py (5444b), audible_goodreads_deal_scout/shared.py (6818b), audible_goodreads_deal_scout/want_to_read_scan.py (32203b), CHANGELOG.md (7917b), config.example.json (726b), examples/preferences.example.md (644b), LICENSE.txt (1073b), PROMPT_REQUEST.md (29654b), README.md (29233b), scripts/audible-goodreads-deal-scout.sh (541b), skill-card.md (2893b), SKILL.md (15922b), TRUST.md (4180b), _meta.json (148b)\n\nArchive v0.1.14: 31 files, 105861 bytes\n\nFiles: agents/openai.yaml (317b), audible_goodreads_deal_scout/__init__.py (209b), audible_goodreads_deal_scout/audible_auth.py (24001b), audible_goodreads_deal_scout/audible_catalog.py (30928b), audible_goodreads_deal_scout/audible_fetch.py (18079b), audible_goodreads_deal_scout/audible_source.py (11790b), audible_goodreads_deal_scout/cli_errors.py (878b), audible_goodreads_deal_scout/constants.py (2361b), audible_goodreads_deal_scout/core.py (47046b), audible_goodreads_deal_scout/delivery.py (15006b), audible_goodreads_deal_scout/diagnostics.py (12624b), audible_goodreads_deal_scout/goodreads_csv.py (6509b), audible_goodreads_deal_scout/goodreads_rating.py (5119b), audible_goodreads_deal_scout/public_cli.py (31845b), audible_goodreads_deal_scout/rendering.py (8792b), audible_goodreads_deal_scout/repo_audit.py (1512b), audible_goodreads_deal_scout/runtime_contract.py (7829b), audible_goodreads_deal_scout/settings.py (5444b), audible_goodreads_deal_scout/shared.py (6818b), audible_goodreads_deal_scout/want_to_read_scan.py (32203b), CHANGELOG.md (7241b), config.example.json (726b), examples/preferences.example.md (644b), LICENSE.txt (1073b), PROMPT_REQUEST.md (29654b), README.md (29062b), scripts/audible-goodreads-deal-scout.sh (541b), skill-card.md (2716b), SKILL.md (15473b), TRUST.md (4180b), _meta.json (148b)\n\nArchive v0.1.13: 30 files, 103485 bytes\n\nFiles: agents/openai.yaml (317b), audible_goodreads_deal_scout/__init__.py (170b), audible_goodreads_deal_scout/audible_auth.py (24001b), audible_goodreads_deal_scout/audible_catalog.py (30928b), audible_goodreads_deal_scout/audible_fetch.py (18079b), audible_goodreads_deal_scout/audible_source.py (11790b), audible_goodreads_deal_scout/cli_errors.py (878b), audible_goodreads_deal_scout/constants.py (2361b), audible_goodreads_deal_scout/core.py (47046b), audible_goodreads_deal_scout/delivery.py (13772b), audible_goodreads_deal_scout/diagnostics.py (11369b), audible_goodreads_deal_scout/goodreads_csv.py (6509b), audible_goodreads_deal_scout/goodreads_rating.py (5119b), audible_goodreads_deal_scout/public_cli.py (31482b), audible_goodreads_deal_scout/rendering.py (8792b), audible_goodreads_deal_scout/repo_audit.py (1512b), audible_goodreads_deal_scout/runtime_contract.py (7829b), audible_goodreads_deal_scout/settings.py (5444b), audible_goodreads_deal_scout/shared.py (6818b), audible_goodreads_deal_scout/want_to_read_scan.py (32203b), CHANGELOG.md (6804b), config.example.json (726b), examples/preferences.example.md (644b), LICENSE.txt (1073b), PROMPT_REQUEST.md (29654b), README.md (28962b), scripts/audible-goodreads-deal-scout.sh (541b), SKILL.md (15342b), TRUST.md (4180b), _meta.json (148b)\n\nArchive v0.1.12: 30 files, 102039 bytes\n\nFiles: agents/openai.yaml (317b), audible_goodreads_deal_scout/__init__.py (170b), audible_goodreads_deal_scout/audible_auth.py (21058b), audible_goodreads_deal_scout/audible_catalog.py (30928b), audible_goodreads_deal_scout/audible_fetch.py (18079b), audible_goodreads_deal_scout/audible_source.py (11790b), audible_goodreads_deal_scout/cli_errors.py (878b), audible_goodreads_deal_scout/constants.py (2361b), audible_goodreads_deal_scout/core.py (47046b), audible_goodreads_deal_scout/delivery.py (13772b), audible_goodreads_deal_scout/diagnostics.py (11369b), audible_goodreads_deal_scout/goodreads_csv.py (6509b), audible_goodreads_deal_scout/goodreads_rating.py (5119b), audible_goodreads_deal_scout/public_cli.py (31482b), audible_goodreads_deal_scout/rendering.py (8792b), audible_goodreads_deal_scout/repo_audit.py (1512b), audible_goodreads_deal_scout/runtime_contract.py (7829b), audible_goodreads_deal_scout/settings.py (5444b), audible_goodreads_deal_scout/shared.py (6818b), audible_goodreads_deal_scout/want_to_read_scan.py (32203b), CHANGELOG.md (6417b), config.example.json (726b), examples/preferences.example.md (644b), LICENSE.txt (1073b), PROMPT_REQUEST.md (29306b), README.md (28472b), scripts/audible-goodreads-deal-scout.sh (541b), SKILL.md (14694b), TRUST.md (3767b), _meta.json (148b)\n\nArchive v0.1.11: 30 files, 90865 bytes\n\nFiles: agents/openai.yaml (317b), audible_goodreads_deal_scout/__init__.py (170b), audible_goodreads_deal_scout/audible_auth.py (21058b), audible_goodreads_deal_scout/audible_catalog.py (30789b), audible_goodreads_deal_scout/audible_source.py (13966b), audible_goodreads_deal_scout/cli_errors.py (878b), audible_goodreads_deal_scout/constants.py (2361b), audible_goodreads_deal_scout/core.py (43339b), audible_goodreads_deal_scout/delivery.py (13698b), audible_goodreads_deal_scout/diagnostics.py (8348b), audible_goodreads_deal_scout/goodreads_csv.py (6509b), audible_goodreads_deal_scout/goodreads_rating.py (5119b), audible_goodreads_deal_scout/harness.py (1298b), audible_goodreads_deal_scout/public_cli.py (30860b), audible_goodreads_deal_scout/rendering.py (8792b), audible_goodreads_deal_scout/repo_audit.py (1512b), audible_goodreads_deal_scout/runtime_contract.py (7829b), audible_goodreads_deal_scout/settings.py (5328b), audible_goodreads_deal_scout/shared.py (6818b), audible_goodreads_deal_scout/want_to_read_scan.py (32203b), CHANGELOG.md (5945b), config.example.json (693b), examples/preferences.example.md (644b), LICENSE.txt (1073b), PROMPT_REQUEST.md (13566b), README.md (27468b), scripts/audible-goodreads-deal-scout.sh (541b), SKILL.md (14137b), TRUST.md (3576b), _meta.json (148b)\n\nArchive v0.1.10: 30 files, 89308 bytes\n\nFiles: agents/openai.yaml (317b), audible_goodreads_deal_scout/__init__.py (170b), audible_goodreads_deal_scout/audible_auth.py (21058b), audible_goodreads_deal_scout/audible_catalog.py (30789b), audible_goodreads_deal_scout/audible_source.py (13909b), audible_goodreads_deal_scout/cli_errors.py (878b), audible_goodreads_deal_scout/constants.py (2274b), audible_goodreads_deal_scout/core.py (35556b), audible_goodreads_deal_scout/delivery.py (13698b), audible_goodreads_deal_scout/diagnostics.py (8348b), audible_goodreads_deal_scout/goodreads_csv.py (6509b), audible_goodreads_deal_scout/goodreads_rating.py (5119b), audible_goodreads_deal_scout/harness.py (1298b), audible_goodreads_deal_scout/public_cli.py (29521b), audible_goodreads_deal_scout/rendering.py (8792b), audible_goodreads_deal_scout/repo_audit.py (1512b), audible_goodreads_deal_scout/runtime_contract.py (7640b), audible_goodreads_deal_scout/settings.py (5328b), audible_goodreads_deal_scout/shared.py (6818b), audible_goodreads_deal_scout/want_to_read_scan.py (32203b), CHANGELOG.md (5321b), config.example.json (693b), examples/preferences.example.md (644b), LICENSE.txt (1073b), PROMPT_REQUEST.md (13566b), README.md (27190b), scripts/audible-goodreads-deal-scout.sh (541b), SKILL.md (13883b), TRUST.md (3576b), _meta.json (148b)\n\nArchive v0.1.9: 29 files, 86660 bytes\n\nFiles: agents/openai.yaml (317b), audible_goodreads_deal_scout/__init__.py (170b), audible_goodreads_deal_scout/audible_auth.py (21058b), audible_goodreads_deal_scout/audible_catalog.py (30789b), audible_goodreads_deal_scout/audible_source.py (13909b), audible_goodreads_deal_scout/cli_errors.py (878b), audible_goodreads_deal_scout/constants.py (2274b), audible_goodreads_deal_scout/core.py (35556b), audible_goodreads_deal_scout/delivery.py (13698b), audible_goodreads_deal_scout/diagnostics.py (8348b), audible_goodreads_deal_scout/goodreads_csv.py (6509b), audible_goodreads_deal_scout/goodreads_rating.py (5119b), audible_goodreads_deal_scout/harness.py (1298b), audible_goodreads_deal_scout/public_cli.py (29476b), audible_goodreads_deal_scout/rendering.py (8792b), audible_goodreads_deal_scout/repo_audit.py (1512b), audible_goodreads_deal_scout/runtime_contract.py (7640b), audible_goodreads_deal_scout/settings.py (5328b), audible_goodreads_deal_scout/shared.py (6818b), audible_goodreads_deal_scout/want_to_read_scan.py (32203b), CHANGELOG.md (4938b), config.example.json (693b), examples/preferences.example.md (644b), LICENSE.txt (1073b), PROMPT_REQUEST.md (13566b), README.md (26778b), scripts/audible-goodreads-deal-scout.sh (541b), SKILL.md (11939b), _meta.json (147b)\n\nArchive v0.1.8: 29 files, 85876 bytes\n\nFiles: agents/openai.yaml (317b), audible_goodreads_deal_scout/__init__.py (170b), audible_goodreads_deal_scout/audible_auth.py (21058b), audible_goodreads_deal_scout/audible_catalog.py (30789b), audible_goodreads_deal_scout/audible_source.py (13909b), audible_goodreads_deal_scout/cli_errors.py (878b), audible_goodreads_deal_scout/constants.py (2274b), audible_goodreads_deal_scout/core.py (35556b), audible_goodreads_deal_scout/delivery.py (13698b), audible_goodreads_deal_scout/diagnostics.py (8348b), audible_goodreads_deal_scout/goodreads_csv.py (6509b), audible_goodreads_deal_scout/goodreads_rating.py (5119b), audible_goodreads_deal_scout/harness.py (1298b), audible_goodreads_deal_scout/public_cli.py (29476b), audible_goodreads_deal_scout/rendering.py (8792b), audible_goodreads_deal_scout/repo_audit.py (1512b), audible_goodreads_deal_scout/runtime_contract.py (7640b), audible_goodreads_deal_scout/settings.py (5328b), audible_goodreads_deal_scout/shared.py (6818b), audible_goodreads_deal_scout/want_to_read_scan.py (32203b), CHANGELOG.md (4587b), config.example.json (693b), examples/preferences.example.md (644b), LICENSE.txt (1073b), PROMPT_REQUEST.md (13566b), README.md (26743b), scripts/audible-goodreads-deal-scout.sh (541b), SKILL.md (9995b), _meta.json (147b)","readmeExcerpt":"Skill: Audible Deal Scout Owner: lenpr Summary: Evaluate an Audible daily promotion against Goodreads public score, optional Goodreads CSV shelves, optional freeform reading notes, optional delivery rules,... Tags: latest:0.1.18, stable:0.1.13 Version history: v0.1.18 | 2026-07-20T03:29:40.028Z | user Harden scheduled execution, auth, config, scans, and release validation. v0.1.17 | 2026-07-19T20:31:58.493Z | user Te","codeSnippets":[],"executableExamples":[{"language":"json","snippet":"{\n  \"schemaVersion\": 1,\n  \"goodreads\": {\n    \"status\": \"resolved | no_match | lookup_failed\",\n    \"url\": \"string | null\",\n    \"title\": \"string | null\",\n    \"author\": \"string | null\",\n    \"averageRating\": \"number | null\",\n    \"ratingsCount\": \"integer | null\",\n    \"evidence\": \"string | null\"\n  },\n  \"fit\": {\n    \"status\": \"written | not_applicable | unavailable\",\n    \"sentence\": \"string | null\"\n  }\n}"},{"language":"bash","snippet":"sh \"{baseDir}/scripts/audible-goodreads-deal-scout.sh\" prepare --config-path \"<config-path>\" --invocation-mode manual"},{"language":"bash","snippet":"sh \"{baseDir}/scripts/audible-goodreads-deal-scout.sh\" setup \\\n  --config-path \"<config-path>\" \\\n  --audible-marketplace \"<marketplace>\" \\\n  --threshold \"<threshold>\" \\\n  [--goodreads-csv \"<csv-path>\"] \\\n  [--notes-file \"<notes-file>\"] \\\n  [--notes-text \"<inline notes>\"] \\\n  [--delivery-channel \"telegram\"] \\\n  [--delivery-target \"<target>\"] \\\n  [--delivery-policy \"positive_only\"] \\\n  [--daily-automation | --no-daily-automation] \\\n  [--no-delivery] \\\n  [--register-cron]"},{"language":"bash","snippet":"sh \"{baseDir}/scripts/audible-goodreads-deal-scout.sh\" scan-want-to-read \\\n  --config-path \"<config-path>\" \\\n  [--audible-auth-path \"<auth-path>\"] \\\n  [--limit 40] \\\n  [--offset 0] \\\n  [--scan-order newest] \\\n  [--progress plain] \\\n  [--no-goodreads-rating-enrichment] \\\n  [--goodreads-rating-limit 20] \\\n  [--output-json \"<json-path>\"] \\\n  [--output-md \"<markdown-path>\"]"},{"language":"bash","snippet":"sh \"{baseDir}/scripts/audible-goodreads-deal-scout.sh\" audible-auth-start \\\n  --auth-path \"<workspace>/.audible-goodreads-deal-scout/audible-auth.json\" \\\n  --audible-marketplace us\n\nsh \"{baseDir}/scripts/audible-goodreads-deal-scout.sh\" audible-auth-finish \\\n  --auth-path \"<workspace>/.audible-goodreads-deal-scout/audible-auth.json\" \\\n  --redirect-url \"<final-amazon-redirect-url>\""},{"language":"bash","snippet":"sh \"{baseDir}/scripts/audible-goodreads-deal-scout.sh\" doctor \\\n  --config-path \"<config-path>\"\n\nsh \"{baseDir}/scripts/audible-goodreads-deal-scout.sh\" audible-auth-status \\\n  --auth-path \"<workspace>/.audible-goodreads-deal-scout/audible-auth.json\""}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: audible-goodreads-deal-scout\ndescription: Evaluate an Audible daily promotion against Goodreads public score, optional Goodreads CSV shelves, optional freeform reading notes, optional delivery rules, and manual Want-to-Read discount scans. Use for first-run setup, deal checks, scheduled sends, and on-demand Goodreads backlog audits.\nlicense: MIT-0\nmetadata: {\"openclaw\":{\"emoji\":\"🎧\",\"skillKey\":\"audible-goodreads-deal-scout\",\"homepage\":\"https://github.com/lenpr/audible-goodreads-deal-scout\",\"category\":\"media\",\"requires\":{\"bins\":[\"sh\"],\"anyBins\":[\"python3\",\"python\"]}}}\n---\n\n# Audible Goodreads Deal Scout\n\nNever miss an Audible deal for a book you actually want to read.\n\nAudible Goodreads Deal Scout is a **ClawHub / OpenClaw skill** that checks Audible promotions against Goodreads ratings, your Goodreads shelves, and optional reading-taste notes. It is built for people who want fewer random deal notifications and more \"this is actually relevant to me\" recommendations.\n\nThe goal is not to buy more audiobooks. The goal is to notice the few Audible deals that match books you already care about.\n\n## What It Does\n\nUse this skill to:\n- check today's Audible daily deal and get a short recommendation\n- see whether the deal is already on your Goodreads Want-to-Read shelf\n- suppress books you already marked as read or currently reading\n- scan your Goodreads Want-to-Read shelf for Audible titles with visible discounts\n- rank discounted Want-to-Read matches by deal strength and Goodreads signal\n- create personalized recommendations from your Goodreads shelves, ratings, reviews, and taste notes\n- explain why a book may or may not fit your reading preferences, instead of only showing a generic score\n- optionally check member-visible Audible cash prices with a local Audible auth token\n- optionally deliver good matches to Telegram or another configured OpenClaw channel\n\nIf you do not want personalization, the skill still works with public Goodreads ratings only.\n\nThis skill reports opportunities only. It does not buy, reserve, check out, redeem credits, manage subscriptions, or complete purchases.\n\n## Getting The Most Value\n\nThe best setup uses:\n1. A Goodreads library CSV from the official Goodreads `Import and Export` page.\n2. Short taste notes about books, authors, genres, pacing, and themes you like or avoid.\n3. Optional Audible authentication when you want member-visible cash prices in Want-to-Read scans.\n\nWith those pieces, the skill can track today's Audible promotion, compare it against your Goodreads library, explain personal fit, and scan your Want-to-Read shelf for Audible titles that look discounted or priced below list.\n\n## Trust And Data Access\n\nThe skill reads only the files and services needed for its configured workflow.\n\n| Data or service | When used | Purpose |\n| --- | --- | --- |\n| Config file | Setup, daily checks, scans, delivery | Stores marketplace, thresholds, paths, privacy mode, and optional delivery settings |\n| Goodreads CSV | "},{"path":"README.md","content":"# Audible Goodreads Deal Scout\n\nNever miss an Audible deal for a book you actually want to read.\n\nAudible Goodreads Deal Scout is a **ClawHub / OpenClaw skill** that checks Audible promotions against Goodreads ratings, your Goodreads shelves, and optional reading-taste notes. It is built for people who want fewer random deal notifications and more \"this is actually relevant to me\" recommendations.\n\nThe goal is not to buy more audiobooks. The goal is to notice the few Audible deals that match books you already care about.\n\nThe skill reports opportunities only. It does not buy, reserve, check out, redeem credits, manage subscriptions, or complete purchases.\n\nFor a concise security and data-access summary, see [TRUST.md](TRUST.md).\n\n## Use This Skill To\n\nUse this skill to:\n\n- Check today's Audible daily deal and get a short recommendation.\n- See whether the deal is already on your Goodreads Want-to-Read shelf.\n- Suppress books you already marked as read or currently reading.\n- Scan your Goodreads Want-to-Read shelf for Audible titles with visible discounts.\n- Rank discounted Want-to-Read matches by deal strength and Goodreads signal.\n- Create highly personalized recommendations from your Goodreads shelves, ratings, reviews, and taste notes.\n- Explain why a book may or may not fit your reading preferences, instead of only showing a generic score.\n- Optionally check member-visible Audible cash prices with a local Audible auth token.\n- Optionally deliver good matches to Telegram or another configured OpenClaw channel.\n\nIf you do not want personalization, the skill still works with public Goodreads ratings only.\n\n## How To Get The Most Value\n\nThe skill works with public data only, but it gets much better when you give it a little personal context.\n\nThe best setup is:\n\n1. Export your Goodreads library CSV.\n   Use the official Goodreads library exporter from Goodreads' `Import and Export` page. This lets the skill know what you already read, what you are currently reading, and what is on your Want-to-Read shelf.\n2. Add short taste notes.\n   A few paragraphs are enough. You can write them yourself, dictate them quickly, or ask an AI to draft taste notes from your favorite books, disliked books, preferred genres, and reading habits. These notes help the skill explain whether a deal actually fits you, not just whether it is popular.\n3. Optionally add Audible authentication for member prices.\n   Anonymous Audible pages often hide cash prices or show credit-based buying options. If you provide a local Audible auth token, the skill can check member-visible cash prices for matched titles and produce a more useful Want-to-Read discount report.\n\nWith all three pieces, the skill can help keep track of:\n\n- today's Audible promotion\n- whether the book is already in your Goodreads library\n- whether it is on your Want-to-Read shelf\n- whether it looks like a good fit for your taste\n- which Want-to-Read books are available on Audible\n- which matched titles appear discoun"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn74j40rqb6m5s0whvynrxcq098212ny\",\n  \"slug\": \"audible-goodreads-deal-scout\",\n  \"version\": \"0.1.18\",\n  \"publishedAt\": 1784518180028\n}"},{"path":"CHANGELOG.md","content":"# Changelog\n\n## Unreleased\n\n## 0.1.18 - 2026-07-19\n\n- Add a deterministic scheduled gate so positive-only suppressions do not start an agent or create cron run history\n- Use OpenClaw condition triggers, lightweight bootstrap context, and disabled model thinking for substantially smaller scheduled runs\n- Reconcile and diagnose cron trigger, context, schedule, IANA timezone, and delivery-route drift; support explicit automation and route removal\n- Preserve unknown and marketplace-specific config values, resolve configured relative paths from the config directory, and fail closed on malformed config or state\n- Bind scheduled delivery and state updates to the config/state paths recorded by the current prepare artifact\n- Harden Audible auth storage, refresh-token rotation, permissions, schema checks, redirect handling, response bounds, and sensitive-data redaction\n- Validate public HTTP redirects before following them, bound compressed/decompressed responses, and tighten Audible and Goodreads URL paths\n- Prefer strong Audible catalog matches regardless of candidate order and restrict Goodreads aggregate ratings to valid Book entities\n- Validate scan bounds, preflight authenticated scans, preserve zero-valued options, and return partial-failure exit codes reliably\n- Make delivery success and dry-run results unambiguous and reject successful exit codes carrying failure payloads\n- Audit the actual ClawHub publish bundle, require every runtime module, and enforce package/changelog/release-version parity\n- Add regression and permutation coverage for security, setup, scheduling, state, parsing, delivery, publishing, and scan failure boundaries\n\n## 0.1.17\n\n- Publish the post-0.1.16 test release pointer used to verify ClawHub release metadata\n- Build a bounded candidate-specific fit-evidence artifact and require more concrete, review-grounded recommendation prose\n- Strictly validate runtime output fields, types, Goodreads URLs, rating ranges, fit status semantics, and fit paragraph length\n- Split preparation into focused fetch, library, short-circuit, and artifact phases and remove implicit `core` re-exports\n- Harden Audible and Goodreads parsers for JSON-LD graphs, markup attribute variants, nested text, lowercase product ids, and trailing price punctuation\n- Surface OpenClaw command timeouts and invalid JSON instead of treating ambiguous subprocess output as success or an empty cron list\n- Split the test suite by behavior and add DST, expiry, cache, atomic-write, subprocess, parser-variant, and evidence-selection coverage\n- Exclude `PROMPT_REQUEST.md` from the published ClawHub runtime bundle\n\n## 0.1.16\n\n- Route registered OpenClaw cron jobs through the configured delivery channel and target\n- Reconcile existing Audible cron jobs when their schedule, IANA timezone, message, or delivery route drifts\n- Make live cron diagnostics fail on active schedule or delivery mismatches\n\n## 0.1.15\n\n- Preserve existing config values when rerunning setup or registering cro"},{"path":"examples/preferences.example.md","content":"I usually like fiction that is idea-driven, formally interesting, and emotionally controlled rather than sentimental.\n\nAuthors and books I tend to like:\n- Ursula K. Le Guin\n- George Orwell\n- Kazuo Ishiguro\n- David Mitchell\n- literary science fiction\n- political satire\n- speculative fiction with philosophical weight\n\nWhat I usually do not like:\n- generic airport thrillers\n- fantasy that is mostly lore and worldbuilding\n- romance-forward plots\n- books that rely on shock value more than ideas\n\nWhen in doubt, I prefer:\n- originality over comfort\n- structure and voice over plot mechanics\n- books that leave something to think about afterward"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":1912,"uniquenessScore":44,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-10T03:37:29.815Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-10T03:37:29.815Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-10T07:08:11.544Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}