imprint-mcp 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/CHANGELOG.md +168 -0
  2. package/LICENSE +21 -0
  3. package/README.md +322 -0
  4. package/examples/discoverandgo/README.md +57 -0
  5. package/examples/discoverandgo/book_discoverandgo_museum_pass/cron.json +8 -0
  6. package/examples/discoverandgo/book_discoverandgo_museum_pass/index.ts +89 -0
  7. package/examples/discoverandgo/book_discoverandgo_museum_pass/workflow.json +39 -0
  8. package/examples/echo/README.md +37 -0
  9. package/examples/echo/echo_test/index.ts +31 -0
  10. package/examples/google-flights/search_google_flights/index.ts +101 -0
  11. package/examples/google-flights/search_google_flights/parser.test.ts +140 -0
  12. package/examples/google-flights/search_google_flights/parser.ts +189 -0
  13. package/examples/google-flights/search_google_flights/playbook.yaml +130 -0
  14. package/examples/google-flights/search_google_flights/workflow.json +48 -0
  15. package/examples/google-hotels/search_google_hotels/index.ts +194 -0
  16. package/examples/google-hotels/search_google_hotels/parser.test.ts +168 -0
  17. package/examples/google-hotels/search_google_hotels/parser.ts +330 -0
  18. package/examples/google-hotels/search_google_hotels/playbook.yaml +125 -0
  19. package/examples/google-hotels/search_google_hotels/workflow.json +111 -0
  20. package/examples/namecheap-domains/search_namecheap_domains/index.ts +144 -0
  21. package/examples/namecheap-domains/search_namecheap_domains/parser.ts +380 -0
  22. package/examples/namecheap-domains/search_namecheap_domains/playbook.yaml +50 -0
  23. package/examples/namecheap-domains/search_namecheap_domains/request-transform.ts +136 -0
  24. package/examples/namecheap-domains/search_namecheap_domains/workflow.json +97 -0
  25. package/examples/southwest/README.md +81 -0
  26. package/examples/southwest/search_southwest_flights/backends.json +23 -0
  27. package/examples/southwest/search_southwest_flights/cron.json +19 -0
  28. package/examples/southwest/search_southwest_flights/index.ts +110 -0
  29. package/examples/southwest/search_southwest_flights/playbook.yaml +46 -0
  30. package/examples/southwest/search_southwest_flights/workflow.json +54 -0
  31. package/package.json +78 -0
  32. package/prompts/compile-agent.md +580 -0
  33. package/prompts/intent-detection.md +198 -0
  34. package/prompts/playbook-compilation.md +279 -0
  35. package/prompts/request-triage.md +74 -0
  36. package/prompts/tool-candidate-detection.md +104 -0
  37. package/src/cli.ts +1287 -0
  38. package/src/imprint/agent.ts +468 -0
  39. package/src/imprint/app-api-hosts.ts +53 -0
  40. package/src/imprint/backend-ladder.ts +568 -0
  41. package/src/imprint/check.ts +136 -0
  42. package/src/imprint/chromium.ts +211 -0
  43. package/src/imprint/claude-cli-compile.ts +640 -0
  44. package/src/imprint/cli-credential.ts +394 -0
  45. package/src/imprint/codex-cli-compile.ts +712 -0
  46. package/src/imprint/compile-agent-types.ts +40 -0
  47. package/src/imprint/compile-agent.ts +404 -0
  48. package/src/imprint/compile-tools.ts +1389 -0
  49. package/src/imprint/compile.ts +720 -0
  50. package/src/imprint/cookie-jar.ts +246 -0
  51. package/src/imprint/credential-bundle.ts +195 -0
  52. package/src/imprint/credential-extract.ts +290 -0
  53. package/src/imprint/credential-store.ts +707 -0
  54. package/src/imprint/cron.ts +312 -0
  55. package/src/imprint/doctor.ts +223 -0
  56. package/src/imprint/emit.ts +154 -0
  57. package/src/imprint/etld.ts +134 -0
  58. package/src/imprint/freeform-redact.ts +216 -0
  59. package/src/imprint/inject-listener.ts +137 -0
  60. package/src/imprint/install.ts +795 -0
  61. package/src/imprint/integrations.ts +385 -0
  62. package/src/imprint/is-compiled.ts +2 -0
  63. package/src/imprint/json-path.ts +100 -0
  64. package/src/imprint/llm.ts +998 -0
  65. package/src/imprint/load-json.ts +54 -0
  66. package/src/imprint/log.ts +33 -0
  67. package/src/imprint/login.ts +166 -0
  68. package/src/imprint/mcp-compile-server.ts +282 -0
  69. package/src/imprint/mcp-maintenance.ts +1790 -0
  70. package/src/imprint/mcp-server.ts +350 -0
  71. package/src/imprint/multi-progress.ts +69 -0
  72. package/src/imprint/notify.ts +155 -0
  73. package/src/imprint/paths.ts +64 -0
  74. package/src/imprint/playbook-parser.ts +21 -0
  75. package/src/imprint/playbook-runner.ts +465 -0
  76. package/src/imprint/probe-backends.ts +251 -0
  77. package/src/imprint/progress.ts +28 -0
  78. package/src/imprint/record.ts +470 -0
  79. package/src/imprint/redact.ts +550 -0
  80. package/src/imprint/replay-capture.ts +387 -0
  81. package/src/imprint/request-context.ts +66 -0
  82. package/src/imprint/runtime-link.ts +73 -0
  83. package/src/imprint/runtime.ts +942 -0
  84. package/src/imprint/sensitive-keys.ts +156 -0
  85. package/src/imprint/session-diff.ts +409 -0
  86. package/src/imprint/session-merge.ts +198 -0
  87. package/src/imprint/session-writer.ts +149 -0
  88. package/src/imprint/sites.ts +27 -0
  89. package/src/imprint/stealth-fetch.ts +434 -0
  90. package/src/imprint/teach-state.ts +235 -0
  91. package/src/imprint/teach.ts +2120 -0
  92. package/src/imprint/tool-candidates.ts +423 -0
  93. package/src/imprint/tool-loader.ts +186 -0
  94. package/src/imprint/tool-selection.ts +70 -0
  95. package/src/imprint/tracing.ts +508 -0
  96. package/src/imprint/types.ts +472 -0
  97. package/src/imprint/version.ts +21 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,168 @@
1
+ # Changelog
2
+
3
+ All notable changes to Imprint. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) (Added / Changed / Deprecated / Removed / Fixed / Security).
4
+
5
+ ## [0.2.0] — 2026-05-14
6
+
7
+ v0.2 overhauls the teach-to-tool pipeline, adds full observability tracing, and introduces state-aware API replay. 12 new features, 7 bug fixes across 24 commits.
8
+
9
+ ### Added
10
+ - **Multi-tool teach** — `imprint teach` captures multiple tools in a single session with shared request triage across tools for optimized token usage (#23, #29).
11
+ - **Deterministic MCP tools** — teach produces functional, deterministic tool definitions that agents can call reliably (#28).
12
+ - **Full-depth tracing** — LLM calls and agent loop iterations are traced end-to-end for debugging and observability (#31).
13
+ - **Dotenv support** — `.env` file with tracing defaults, auto-loaded by the CLI via dotenv (#32).
14
+ - **State-aware API replay** — replay engine tracks API state across requests for more reliable automation (#24).
15
+ - **Credential manager** — catch login secrets during teach, store in OS keychain, replay via `${credential.X}` placeholders (#14).
16
+ - **Interactive compile provider picker** — choose your LLM provider interactively when compiling (#17).
17
+ - **Claude CLI + MCP compilation** — drive compile-agent via claude-cli and stdio MCP server (#11).
18
+ - **Landing page** — Imprint website at `web/` (#22).
19
+ - **Improved session redaction** — broader PII and credential coverage across content types (#20).
20
+ - **Gitleaks pre-commit hook** — automated secret scanning before commits; fail-closed when gitleaks is not installed.
21
+ - **Teach UX improvements** — keybinding hints in multi-tool select prompt (#26), auto-prompt for missing site and starting URL (#10).
22
+
23
+ ### Changed
24
+ - **Examples layout** — tools now require nested directory structure per tool (#16).
25
+ - **README** — added google-flights and google-hotels examples, removed southwest-seats.
26
+ - **README** — polished for GitHub discoverability and conversion.
27
+
28
+ ### Fixed
29
+ - Wire parserModule and preserve query params in compile-agent (#27).
30
+ - Dispatch tool_use blocks in max_tokens responses (#30).
31
+ - Fix credential/PII leaks in sessions with non-JSON content-types (#13).
32
+ - Use correct field name `stopCount` in parser test (#18).
33
+ - Store recordings outside examples directory (#19).
34
+ - Replace hardcoded API key with env var.
35
+
36
+ ### Documentation
37
+ - State-aware replay guide (#25).
38
+ - CI test count badge.
39
+
40
+ ---
41
+
42
+ ## [0.1.0] — 2026-05-05 (post-sprint polish)
43
+
44
+ A de-slop pass on the v0.1 codebase: deep audit + rearchitect to make the implementation sleek and the docs adoption-friendly. **No behavioral changes to existing verbs** — every demo still works (live-verified end-to-end against Southwest via stealth-fetch). One new verb (`imprint doctor`) added.
45
+
46
+ ### Added
47
+ - **`imprint doctor` verb** — one-shot environment health check (Bun, Chromium binary, Playwright Chromium, Vertex env vars, push providers). Exits 0 on all-pass / 1 on any required failure (CI-friendly). Each failure includes a `→ next step:` hint. Surfaced in README quickstart + docs/troubleshooting.md as the first thing to try.
48
+ - `docs/architecture.md` — data flow diagram, module map, backend ladder cost table, per-example file taxonomy.
49
+ - `docs/glossary.md` — Session, Workflow, Playbook, Backend, Stealth-fetch, Sensor headers, Token TTL refresh, Sentinel, CDP, Credential store, NotifyWhen.
50
+ - `docs/decisions.md` — 12 ADR-style entries (D1-D12) covering the load-bearing calls.
51
+ - `docs/getting-started.md` — 5-minute walkthrough from clone to MCP tool in Claude Desktop.
52
+ - `docs/troubleshooting.md` — predictable failure modes with the same `→ next step:` format the in-code error messages use.
53
+ - `docs/notifications.md` — Pushover + ntfy setup, predicate language for `notifyWhen`.
54
+ - `docs/security.md` — what Imprint stores, redaction guarantees, credential handling, vuln reporting flow.
55
+ - `examples/discoverandgo/README.md` and `examples/echo/README.md` — tutorial-style READMEs (each: what / why interesting / run / what you should see / notes).
56
+ - `CHANGELOG.md` — this file.
57
+ - `CONTRIBUTING.md` — table-stakes contributor guide.
58
+ - Per-verb help: `imprint <verb> --help` shows summary + usage + flags + a concrete example. The verb registry is single-source.
59
+ - Actionable `→ next step:` hints in every user-reachable error message (Pushover/ntfy not set, missing playbook, missing param, no requests in workflow, etc.).
60
+ - `resolveLadder` helper in `backend-ladder.ts` so cron + mcp-server share the auto-ladder expansion logic.
61
+ - MCP tool descriptions now include the operator's recorded narration (`intent.userSaid`) — gives the LLM real context for picking the right tool.
62
+ - Test coverage: `test/compile.test.ts` (+15 tests for shrinkSession + error paths), `test/cli-help.test.ts` (+26 drift-guard tests for VERB_HELP / dispatcher sync), `test/backend-ladder.test.ts` (+5 resolveLadder tests), `test/doctor.test.ts` (+7), additional `test/notify.test.ts` cases for multi-path pricePath. 132 → 193 tests.
63
+ - `bun run check` package.json script — combined typecheck + lint + tests. CI now runs this directly.
64
+ - `bun run imprint <verb>` and `bun run doctor` package.json shortcuts (alternatives to `bun link`).
65
+ - `imprint emit` prints "next steps" after generating, removing the "I have a tool, now what?" friction point.
66
+ - `imprint cron <unknown-site>` now lists the configured sites in the error message ("available sites: a, b, c").
67
+ - "command not found" troubleshooting section explicitly covering the bun-link / PATH failure mode.
68
+ - **Typo suggestions** for unknown verbs: `imprint recrod` → "did you mean `imprint record`?" via Levenshtein distance (≤ 3 edits AND ≤ half-length). Same UX pattern as git/bun. Tested.
69
+ - **Capped cron success-log preview** at 500 chars (full payload still available via IMPRINT_DEBUG=1) so long-running daemons don't flood stderr. Southwest's ~100KB shopping response went from log-flooding to one-line.
70
+ - **`--quiet` flag for `imprint cron`** (and `IMPRINT_QUIET=1` env var) — suppresses info logs on success so OS schedulers (cron, systemd, launchd) only mail/alert when something's actually broken. Failures still surface to stderr (separate code path).
71
+ - **`isDebug()` / `isQuiet()` env helpers** — internal `=== '1'` semantics. Fixes a subtle bug where `if (process.env.IMPRINT_DEBUG)` was truthy for the string `"0"` (non-empty string coerces to true), so `IMPRINT_DEBUG=0` would actually enable debug mode.
72
+ - **Per-verb missing-arg errors point to `--help`**: `imprint record` (no site) → "→ run `imprint record --help` for usage." Shared via the `requirePositional` helper so all 11 positional-taking verbs benefit.
73
+ - **`--param k=v` malformed input** now shows a concrete example (`→ example: --param origin_airport_code=SJC`) instead of just "requires k=v form".
74
+ - **Pipeline next-step hints**: `record` → `redact` → `generate` → `emit` → `cron`. Every successful verb now ends with the exact command for the next step, including the file path produced. A first-time user can chain the entire pipeline by following the printed commands.
75
+ - **MCP no-tools error** suggests the bundled `echo` fixture so first-time users can verify the MCP wire-up before they've recorded anything.
76
+ - **Cron expression error** now shows the format and links crontab.guru.
77
+ - **Vertex project ID error** shows the exact `export ANTHROPIC_VERTEX_PROJECT_ID=…` command and points at `imprint doctor` for the rest of the env-var checklist.
78
+ - **Workflow placeholder error** lists the params that *were* passed (or, if none, shows the exact `--param X=<value>` to add).
79
+ - **`loadJsonFile()` helper** — `src/imprint/load-json.ts`. Single-source for the file-not-found / invalid-JSON / schema-mismatch error pipeline used by cron.ts, emit.ts, compile.ts, and the cli.ts redact case. -44 LOC across the four callers, plus user-friendly messages everywhere ZodError used to spill raw to stderr (cron.json `{badkey:1}` → " - schedule: Required" + minimum example + docs link, instead of `[{code:'invalid_type',...}]`).
80
+ - **Pipeline next-step hints** — `imprint redact`, `generate`, `compile-playbook`, `record`, `check`, `login`, `probe-backends`, `mcp-server` (no-tools path) all now print "next step: imprint <verb> ..." after a successful run or hint-worthy error, so the full pipeline can be chained without alt-tabbing to docs.
81
+ - **isDebug() / isQuiet() env helpers** — `=== '1'` semantics (not truthy coercion), so `IMPRINT_DEBUG=0` actually disables. Replaces 8 raw `process.env.IMPRINT_DEBUG` checks across record.ts, chromium.ts, cron.ts, cli.ts.
82
+ - **`tryParseParamKV()` helper** in cli.ts — return-null-on-error pattern eliminates the duplicated try/catch for the two `--param` callers.
83
+ - **Test coverage gap-fills**: `test/check.test.ts` (+8 tests pinning warning heuristics), `test/load-json.test.ts` (+7 tests pinning the shared error shape), `test/sites.test.ts` (+5 tests pinning availableSitesHint branches).
84
+ - **`availableSitesHint()` shared across cron / probe-backends / mcp-server** — extracted from cron.ts to `src/imprint/sites.ts`. Now `imprint probe-backends <typo>` and `imprint mcp-server --site <typo>` also list the actual sites under examples/ so users can spot a one-character typo.
85
+ - **MCP server version single-sourced** — was hard-coded `'0.1.0'`; now reads from the same `VERSION` constant the CLI uses, eliminating a future drift hazard on package.json bumps.
86
+ - **Vertex SDK error enrichment** — `llm.ts` wraps `messages.create` and translates the four common SDK errors (404 model not enabled in region, 401 not authenticated, 403 permission denied, 429 quota) into actionable messages with the exact `gcloud` / IAM / Model Garden link to fix. The raw SDK error is preserved as the JS `cause` chain (visible under `IMPRINT_DEBUG=1`). Documented in docs/troubleshooting.md.
87
+ - **Credential store malformed-file error** — `loadCredentialStore` now throws with the file path + "→ delete and re-run \`imprint login <site>\`" hint instead of letting `JSON.parse` throw bare.
88
+ - **Test coverage for the JSON extractor** — `test/llm.test.ts` (+9 tests for `extractJsonObject`'s fenced-block / nested-brace / escaped-quote branches).
89
+ - **`assemble` next-step hint** — points users to `imprint check` after recovering a session.json from a partial .jsonl. Closes the last verb that was missing a next-step pointer.
90
+ - **Credential placeholder error** matches the param error style — lists available credential keys and suggests re-running `imprint login` if the named key is missing. Helps when the credential store has a partial set (e.g. session_id captured but patron_id wasn't).
91
+ - **`notifyWhen` decision logging** — every cron tick now logs `notifyWhen X: matched → pushing` or `notifyWhen X: no match (predicate ran, threshold not crossed)`. Silent no-match used to confuse users. Suppressed by `--quiet`.
92
+ - **Vertex error troubleshooting docs** — `docs/troubleshooting.md` covers the four Vertex SDK error buckets (404 / 401 / 403 / 429) with the exact gcloud / IAM / Model Garden remediation for each.
93
+ - **D13 + D14 added to `docs/decisions.md`** — three-tool dead-code defense (knip + tsc-strict + madge) and "user-friendly errors are worth the LOC" become ADR entries.
94
+ - **`scripts/mcp-smoke-test.ts` fixed** — was using positional `discoverandgo` (wrong syntax for the `--site=<name>` flag) AND requiring a generated demo. Now defaults to the bundled `echo` fixture so it actually works on a clean checkout. Override via `IMPRINT_SMOKE_SITE=<other>`.
95
+ - **Single source of truth for the backend enum** — `BackendsCacheSchema` previously duplicated `['fetch', 'stealth-fetch', 'playbook']` literally. Now derives from `ReplayBackendSchema.exclude(['auto'])`. Adding a new backend updates one place.
96
+ - **Tighter type narrowing** — `runWithLadder` parameter changed from `ReplayBackend[]` to `ConcreteBackend[]` (= `Exclude<ReplayBackend, 'auto'>`); the unreachable `case 'auto'` defensive throw deleted.
97
+ - **Zero dead code, enforced** — three-tool defense:
98
+ - `knip` (unused exports/files/types/deps)
99
+ - `tsc` (`noUnusedLocals` + `noUnusedParameters` enabled — unused locals/params/imports)
100
+ - `madge` (circular dependencies)
101
+ All three are part of `bun run check` and CI. Removed 19 unused value exports, 35 unused type exports, plus a duplicate alias. Internal-only Options/Result interfaces are no longer exported (TypeScript structural typing means callers don't need a named import). Adding new dead exports / circular deps / unused symbols now fails CI.
102
+
103
+ ### Changed
104
+ - **Module reshape**: clearer file boundaries.
105
+ - `replay-backend.ts` → `backend-ladder.ts` (clearer name; "replay" was jargon)
106
+ - `workflow-runtime.ts` → `runtime.ts` (the prefix was redundant inside `imprint/`)
107
+ - `discover-tools.ts` → `tool-loader.ts`
108
+ - `playbook-types.ts` → folded into `types.ts`
109
+ - **Compiler unification**: `generate.ts` (208 LOC) + `playbook-compiler.ts` (130 LOC) collapsed into `compile.ts` (320 LOC). Skeleton (read session → redact → slim → call LLM → parse → validate → write) shared; per-task differences (slim/prompt/parser/schema) parameterized via a `CompileTask<T>` config.
110
+ - **README**: rewritten for adoption — leads with value prop + 60-second quickstart + demo table. Verb table replaced with pointer to `imprint --help`. ~285 → ~109 lines.
111
+ - **CLI HELP**: top-level reorganized into CAPTURE / COMPILE / RUN groups with one-liner per verb; pointer to per-verb help.
112
+ - **CLAUDE.md**: trimmed from 60 lines of pre-sprint design doc to a slim ~30-line agent-context file. All load-bearing content relocated to `docs/` (per the "don't drop documentation, move it" rule).
113
+ - **Comment hygiene**: stripped design-doc preambles, defensive validation for impossible scenarios, `log("starting…")`/`log("done in Yms")` pairs, and over-documented helpers whose docstring just restated the signature. Net `-691` LOC across `src/imprint/` + `src/cli.ts`.
114
+ - **Test pruning**: consolidated redundant schema tests, parametrized micro-variations, dropped low-signal tests.
115
+ - **Single source of truth for VERSION**: `src/imprint/version.ts` reads the version once from `package.json`. cli.ts, record.ts, probe-backends.ts all import from there — no more drift on bumps.
116
+ - **`pricePath` accepts an array of fallback paths** (backward-compatible with single-string). Fixes a real bug in the southwest cron where `notifyWhen` silently never fired on the stealth-fetch backend (raw API shape) but worked on the playbook backend (reshaped output). Now both shapes are accepted.
117
+ - **package.json description** rewritten to match the README tagline (was a technical surface description).
118
+
119
+ ### Removed
120
+ - `src/imprint/replay-backend.ts`, `src/imprint/workflow-runtime.ts`, `src/imprint/discover-tools.ts`, `src/imprint/playbook-types.ts` (renamed/folded; see Changed).
121
+ - `src/imprint/generate.ts`, `src/imprint/playbook-compiler.ts` (merged into `compile.ts`).
122
+ - `test/sanity.test.ts` — its 3 cases tested Zod's `safeParse` on inline schemas, not Imprint logic.
123
+ - `scripts/minimal-mcp.ts`, `scripts/minimal-mcp-with-import.ts`, `scripts/min-node-mcp.ts` — superseded MCP scratchpads from v0.1 bring-up.
124
+ - `scripts/zoo-sniper.py` — standalone Python script for a personal use case (Zoo Pass automation), unrelated to imprint's pipeline. Pre-pivot artifact.
125
+
126
+ ### Metrics
127
+
128
+ | | Before | After |
129
+ |---|---|---|
130
+ | `src/imprint/` + `src/cli.ts` LOC | 5,828 | 5,714 (-2%, includes +137 LOC for new doctor verb + 5 new shared helpers: compile/doctor/version/load-json/sites) |
131
+ | Source files | 26 | 25 (− 4 renames/folds + 5 new) |
132
+ | Tests | 137 / 13 files | 238 / 20 files (more user-path coverage) |
133
+ | README | sprint-changelog flavor (285 lines) | adoption-friendly (110 lines) |
134
+ | Docs files | 3 | 10 (+ CHANGELOG, CONTRIBUTING, scripts/README) |
135
+ | CLI verbs | 12 | 13 (+ doctor) |
136
+ | ADR entries | — | 14 (D1-D14, including D13 dead-code defense + D14 errors-over-LOC) |
137
+
138
+ ---
139
+
140
+ ## [0.1.0] — 2026-04 / 2026-05 (sprint)
141
+
142
+ Initial public release. Two-week sprint to ship the full pipeline + two working demos.
143
+
144
+ ### Added
145
+ - `imprint record` — CDP-based browser session capture with stdin narration loop, JSONL streaming, sidecar Session JSON on close.
146
+ - `imprint redact` — credential / PII scrub with `[REDACTED:N]` markers preserving shape for the LLM.
147
+ - `imprint generate` — Vertex Anthropic compilation of session → `workflow.json`.
148
+ - `imprint compile-playbook` — Vertex Anthropic compilation of session → `playbook.yaml` (DOM replay artifact, switched from markdown to YAML mid-sprint).
149
+ - `imprint emit` — code generation of `examples/<site>/<toolName>/index.ts` from `workflow.json`.
150
+ - `imprint cron` — polling daemon with multi-provider notifications (Pushover + ntfy) and `notifyWhen: price_below` predicate.
151
+ - `imprint mcp-server` — MCP server (stdio + Streamable HTTP) on the official `@modelcontextprotocol/sdk`.
152
+ - `imprint playbook` — direct Playwright execution of a YAML playbook.
153
+ - `imprint probe-backends` — per-site backend probing with cached `backends.json`.
154
+ - `imprint login` — credential extraction from a recorded session into a per-site credential store.
155
+ - **Backend ladder** — `fetch → stealth-fetch → playbook` with `auto` mode that escalates only on FORBIDDEN.
156
+ - **stealth-fetch** — Playwright-bootstrapped sensor token mint + native fetch augmented with those tokens. Defeats Akamai (verified vs. Southwest: 403 → 200 with real flight data).
157
+ - Working demo: `examples/southwest` (live fare watcher).
158
+ - Working demo: `examples/discoverandgo` (authed museum-pass booking).
159
+
160
+ ### Decisions made
161
+ - Approach: Teach + Replay (not Teach + Expand).
162
+ - Network-level capture (CDP) over vision-based.
163
+ - Two artifacts per recording (workflow.json + playbook.yaml) so the ladder always has a fallback.
164
+ - YAML for the playbook format (replaced 425 LOC of hand-rolled markdown parsing with `YAML.parse` + Zod).
165
+ - Probe-at-record-time + cached `backends.json` to skip futile rungs.
166
+ - MCP stdio default; HTTP opt-in.
167
+
168
+ See [docs/decisions.md](docs/decisions.md) for the full list with rationale.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ashay Changwani
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,322 @@
1
+ <h1 align="center">Imprint</h1>
2
+
3
+ <p align="center">
4
+ <strong>Don't do anything twice. Teach your AI agent once, and it remembers forever.</strong>
5
+ </p>
6
+
7
+ <p align="center">
8
+ <a href="https://github.com/ashaychangwani/imprint/actions/workflows/test.yml"><img src="https://github.com/ashaychangwani/imprint/actions/workflows/test.yml/badge.svg" alt="Tests"></a>
9
+ <img src="https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/ashaychangwani/cbd3134e06fb4fabf24aed94b251bdfd/raw/test-count.json" alt="Test count">
10
+ <a href="https://github.com/ashaychangwani/imprint/releases"><img src="https://img.shields.io/github/v/release/ashaychangwani/imprint?label=release" alt="Release"></a>
11
+ <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue" alt="MIT License"></a>
12
+ <a href="https://github.com/ashaychangwani/imprint/stargazers"><img src="https://img.shields.io/github/stars/ashaychangwani/imprint?style=social" alt="GitHub Stars"></a>
13
+ </p>
14
+
15
+ <br>
16
+
17
+ ```bash
18
+ bun install -g imprint-mcp
19
+ imprint teach southwest --url https://www.southwest.com
20
+ ```
21
+
22
+ That's it. Imprint opens a browser, you drive the workflow, and it compiles a deterministic **MCP tool** your AI agent can call from then on. No tokens burned on exploration, no "the LLM clicked the wrong button" variance. The recording *is* the executable.
23
+
24
+ <br>
25
+
26
+ ## See it in action
27
+
28
+ After teaching, your agent has a tool called `search_namecheap_domains`. The compile-agent reverse-engineered the site's CRC32 URL signing scheme from a captured JavaScript bundle, chains five API endpoints, and merges availability + pricing + aftermarket data:
29
+
30
+ ```
31
+ $ claude "search for getimprint on Namecheap, under $20/yr renewal"
32
+
33
+ getimprint.com taken registered 2008 GoDaddy.com, LLC
34
+ getimprint.dev available $12.98/yr (19% off) renews $20.98/yr
35
+ getimprint.org available $7.48/yr (42% off) renews $15.98/yr
36
+ getimprint.fyi available $6.98/yr renews $9.68/yr
37
+ getimprint.xyz available $2.00/yr (90% off) renews $19.48/yr
38
+ ```
39
+
40
+ Real-time domain availability with per-request URL signing — the agent wrote the signing function itself by reading the site's JS bundle.
41
+
42
+ <br>
43
+
44
+ ## How it works
45
+
46
+ <table>
47
+ <tr>
48
+ <td width="33%">
49
+
50
+ ### 1. Teach
51
+
52
+ ```bash
53
+ imprint teach mysite \
54
+ --url https://example.com
55
+ ```
56
+
57
+ A browser opens. You drive the workflow and narrate what you're doing. Imprint records every network request and DOM interaction.
58
+
59
+ Raw recordings are stored locally under `~/.imprint/<site>/sessions/`, and each generated tool lives under `~/.imprint/<site>/<toolName>/` by default, outside the repo. The generated `index.ts` imports from `imprint/runtime` via a `node_modules/imprint` symlink that Imprint maintains automatically — created on `emit`, self-healed at runtime if a worktree moves or vanishes (so the next `imprint mcp-server`/`cron`/`probe-backends` repairs a stale link without re-emitting). The tracked `examples/` tree remains as source fixtures and demos.
60
+
61
+ </td>
62
+ <td width="33%">
63
+
64
+ ### 2. Compile
65
+
66
+ Imprint generates replay artifacts:
67
+
68
+ - **`workflow.json`** — API-level replay (fast, with named state captures)
69
+ - **`playbook.yaml`** — DOM-level fallback (universal)
70
+ - **`request-transform.ts`** — URL signing when the API requires per-call tokens (optional)
71
+
72
+ Both artifacts are written into the generated tool directory (`~/.imprint/<site>/<toolName>/`). `compile-playbook` uses that nested location by default so cron and MCP discovery can see the fallback without a custom `--out`.
73
+
74
+ Credentials and PII are redacted automatically: credential values become `${credential.NAME}` placeholders, sensitive values become redaction markers that preserve equality within the artifact, and a supplemental free-form scan catches common emails, phone numbers, SSNs, payment cards, JWTs, API keys, private keys, database URLs, and webhook URLs before LLM compile.
75
+
76
+ </td>
77
+ <td width="34%">
78
+
79
+ ### 3. Use
80
+
81
+ A typed MCP tool is generated and wired into your AI platform. Re-run `imprint install <site>` any time to add the same emitted MCP server to another platform, or remove it later with `imprint uninstall <site>`.
82
+
83
+ </td>
84
+ </tr>
85
+ </table>
86
+
87
+ > All three steps happen in a single `imprint teach` command.
88
+
89
+ <br>
90
+
91
+ ## Why Imprint?
92
+
93
+ Other browser-tool frameworks (browser-use, Computer Use) ask the LLM to **decide every click at runtime**.
94
+
95
+ | | Imprint | browser-use / Computer Use |
96
+ |---|---|---|
97
+ | **How it works** | Record once, replay deterministically | LLM decides every click at runtime |
98
+ | **Token cost** | Zero at runtime | Scales with workflow complexity |
99
+ | **Reliability** | Deterministic — same input, same output | Variable — exploration can diverge |
100
+ | **Bot detection** | Real Chromium + stealth-fetch | Detectable automation fingerprint |
101
+ | **When it breaks** | Automatic fallback via backend ladder | No fallback |
102
+ | **Time to result** | 200ms – 9s | 30s+ |
103
+
104
+ <br>
105
+
106
+ ## Install
107
+
108
+ ### npm (requires [Bun](https://bun.sh) >= 1.3)
109
+
110
+ ```bash
111
+ bun install -g imprint-mcp
112
+ ```
113
+
114
+ Or run without installing: `bunx imprint-mcp teach southwest --url https://www.southwest.com`
115
+
116
+ ### Standalone binary (no Bun needed)
117
+
118
+ ```bash
119
+ curl -fsSL https://raw.githubusercontent.com/ashaychangwani/imprint/main/scripts/install.sh | bash
120
+ ```
121
+
122
+ The standalone binary supports `mcp-server`, `install`, `cron`, and `credential` commands.
123
+ Browser commands (`teach`, `record`, `login`, `playbook`) require a full Bun + Playwright install.
124
+
125
+ ### From source
126
+
127
+ ```bash
128
+ git clone https://github.com/ashaychangwani/imprint.git && cd imprint
129
+ bun install && bun link
130
+ ```
131
+
132
+ ### Browser commands
133
+
134
+ The `teach`, `record`, `login`, and `playbook` commands need Playwright's Chromium. Install it once:
135
+
136
+ ```bash
137
+ bunx playwright install chromium
138
+ ```
139
+
140
+ ### LLM providers
141
+
142
+ Imprint detects LLM providers from what's already on your system:
143
+
144
+ | Priority | Provider | Triggered by |
145
+ |---|---|---|
146
+ | 1 | `claude-cli` | `claude` on PATH (Claude Code subscription) |
147
+ | 2 | `codex-cli` | `codex` on PATH (Codex subscription) |
148
+ | 3 | `anthropic-api` | `ANTHROPIC_API_KEY` env var |
149
+ | 4 | `cursor-cli` | `cursor` on PATH (generic prompt/playbook compile only; not `teach`/`generate`) |
150
+
151
+ ```bash
152
+ imprint doctor
153
+ ```
154
+
155
+ Shows which providers are detected. Interactive `imprint teach` prompts you to choose when multiple compatible compile providers are available, and also lists undetected providers as setup-help entries. Pick one of those help entries to see exactly which CLI or environment variable to add so it will be detected next time.
156
+
157
+ To force a specific provider and skip the picker, pass `--provider <name>` to `teach`, `generate`, or `compile-playbook`. `teach` and `generate` require a compile-agent provider (`claude-cli`, `codex-cli`, or `anthropic-api`); `compile-playbook` can also use `cursor-cli`.
158
+
159
+ After selecting a provider, `teach` prompts for a **model** (e.g. `claude-opus-4-7` vs `claude-sonnet-4-6` for Anthropic, `gpt-5.4` vs `o3` for Codex). Override with `--model <name>`. Each tool compiles with a **5-minute timeout** by default; override with `--timeout <duration>` (e.g. `--timeout 10m`, `--timeout 1h`). To skip the replay-and-diff stage (the automated second pass that classifies ephemeral vs constant values), pass `--skip-replay` — faster, but may reduce workflow accuracy for sites with dynamic request parameters.
160
+
161
+ <br>
162
+
163
+ ## Local compile tracing
164
+
165
+ Slow or suspicious compiles can be inspected in a local [Phoenix](https://arize.com/docs/phoenix/self-hosting/deployment-options/terminal) trace UI.
166
+
167
+ ```bash
168
+ # one-time install with uv
169
+ uv tool install arize-phoenix
170
+ phoenix serve
171
+
172
+ # in another terminal
173
+ IMPRINT_TRACE=1 \
174
+ IMPRINT_TRACE_BATCH=false \
175
+ IMPRINT_TRACE_LLM_IO=1 \
176
+ IMPRINT_TRACE_TOOL_IO=1 \
177
+ PHOENIX_COLLECTOR_ENDPOINT=http://localhost:6006 \
178
+ imprint teach namecheap-domains --from-session ~/.imprint/namecheap-domains/sessions/<ts>.json --provider codex-cli
179
+ ```
180
+
181
+ Traces show the full compile pipeline at every level of detail: each `agent.turn.N` span captures per-turn token counts; each `llm.message_with_tools` span records model, provider, input/output tokens, and stop reason; each `agent.tool.X` span times individual tool dispatches. Drill from `cli.teach` → `compile.generate` → `agent.turn.1` → tool calls to find exactly which turn or tool is spending tokens. Set `IMPRINT_TRACE_IO_MAX_CHARS` to raise or lower captured payload size. Set `IMPRINT_TRACE_INPUT_USD_PER_1M` and `IMPRINT_TRACE_OUTPUT_USD_PER_1M` to add estimated cost attributes.
182
+
183
+ <br>
184
+
185
+ ## Platform support
186
+
187
+ At the end of `imprint teach`, you pick your AI platform and Imprint handles the wiring:
188
+
189
+ | Platform | Integration |
190
+ |---|---|
191
+ | **Claude Code** | Automatic — runs `claude mcp add` for you |
192
+ | **Codex CLI** | Automatic — runs `codex mcp add` for you |
193
+ | **Claude Desktop** | Paste-ready JSON config |
194
+ | **OpenClaw** | MCP config + SKILL.md export |
195
+ | **Hermes** | MCP config + SKILL.md + cron mapping |
196
+
197
+ Each site registers as its own MCP server (`imprint-southwest`, `imprint-discoverandgo`, ...) so tools never collide. See [Integrations](docs/integrations.md) for HTTP transport, Docker, and systemd options.
198
+
199
+ Audit or clean up those registrations with `imprint mcp`:
200
+
201
+ ```bash
202
+ imprint mcp status # registrations + local teach state
203
+ imprint mcp # interactive cleanup TUI
204
+ imprint mcp disable imprint-mysite --yes # reversible; stores a local snapshot
205
+ imprint mcp delete imprint-mysite --yes # removes external MCP registrations only
206
+ ```
207
+
208
+ Raw recordings under `~/.imprint/<site>/sessions/` may contain sensitive browser state. Cleanup commands leave them alone unless you explicitly choose `--local site`.
209
+
210
+ See [MCP Maintenance](docs/mcp-maintenance.md) for status classifications, supported client config files, reversible disable behavior, and local artifact cleanup rules.
211
+
212
+ <br>
213
+
214
+ ## Sharing skills across machines
215
+
216
+ Teach on your laptop, ship the skill to a remote agent (OpenClaw, Hermes, a server-side cron host, ...). Skill folders committed to git contain **zero plaintext credentials** — only placeholders like `${credential.NAME}` / `${state.NAME}` and a `credentials.manifest.json` listing the secrets or durable storage keys the receiver must provision.
217
+
218
+ For credentials, use the **encrypted bundle** flow when you can't (or don't want to) re-type passwords on the receiving machine:
219
+
220
+ ```bash
221
+ # On the laptop where you taught the skill:
222
+ imprint credential export southwest --out southwest.imprintbundle
223
+ # → prompts for a passphrase. The bundle is libsodium-encrypted with an
224
+ # argon2id-derived key. Safe to send via Slack, email, scp, S3, etc.
225
+
226
+ # On the OpenClaw machine (or any other receiver):
227
+ imprint credential import southwest southwest.imprintbundle
228
+ # → prompts for the same passphrase. Decrypts; secrets land in the OS keychain.
229
+ ```
230
+
231
+ Pass the passphrase **out-of-band** (Signal, phone, password manager share — *not* the same channel as the bundle file).
232
+
233
+ After import, the same `imprint mcp-server <site>` config you'd use locally works on the receiver — it resolves credentials from that machine's credential backend and initializes a fresh cookie/state jar for every tool call. If anything's missing, `imprint mcp-server` and `imprint cron` log/fail with the exact `imprint credential set`, `imprint login`, or `imprint credential import` commands you need.
234
+
235
+ See [Sharing Skills](docs/credential-sharing.md) for the full flow including interactive `imprint credential set` (when you can re-type), threat model, rotation, and OpenClaw / Hermes wiring details.
236
+
237
+ <br>
238
+
239
+ ## The backend ladder
240
+
241
+ When an API call gets blocked or needs browser-minted state, Imprint doesn't jump straight to DOM replay. It escalates through the cheapest mode that can satisfy the workflow:
242
+
243
+ | | Speed | Handles |
244
+ |---|---|---|
245
+ | **fetch** | ~200ms | Plain APIs, persisted cookies, in-flight HTTP captures |
246
+ | **fetch-bootstrap** | browser bootstrap + API replay | Pages that only need Chromium to mint cookies, CSRF, storage, or DOM-derived state |
247
+ | **stealth-fetch** | ~12s first call, ~1s after | Akamai, Cloudflare, DataDome, bot-defense state |
248
+ | **playbook** | ~9s | Anything — full DOM replay as fallback |
249
+
250
+ `fetch-bootstrap` is not a default rung for every workflow. `auto` inserts it only when the workflow declares bootstrap metadata, a capture requires browser/stealth bootstrap, or `fetch` returns structured `STATE_MISSING` that a browser bootstrap can satisfy. Every recording still compiles to *both* `workflow.json` and `playbook.yaml`, so the ladder has a DOM fallback when API replay cannot work.
251
+
252
+ State-aware workflows use named captures and `${state.NAME}` placeholders. For example, request A can set a CSRF cookie, request B can project it into a header, and the whole run stays on plain `fetch` without launching Chromium.
253
+
254
+ <br>
255
+
256
+ ## Examples
257
+
258
+ The checked-in `examples/` directory contains committed fixtures and demos. Generated tools from `imprint teach` go into `~/.imprint/<site>/<toolName>/` by default (configurable via `IMPRINT_HOME`). Runtime discovery (cron, MCP, probe-backends) reads `IMPRINT_HOME`, so to run the checked-in examples, point it at the repo's `examples/` directory:
259
+
260
+ You can also install an example directly into an MCP client:
261
+
262
+ ```bash
263
+ imprint install google-flights --source examples --platform claude-desktop
264
+ ```
265
+
266
+ Run `imprint install` with no arguments for an interactive install/uninstall picker. It only shows detected AI platforms; uninstall lists installed `imprint-*` MCP servers directly. For GUI config-file clients such as Claude Desktop, install writes an absolute Bun + Imprint CLI path so the app does not depend on your shell PATH.
267
+
268
+ | Example | What it demonstrates | Run it |
269
+ |---|---|---|
270
+ | [**southwest**](examples/southwest) | Live fare watcher, defeats Akamai bot detection, price-drop notifications | `IMPRINT_HOME=examples imprint cron southwest --once` |
271
+ | [**google-flights**](examples/google-flights) | Real-time flight search across all carriers, parses Google's raw protobuf response | `IMPRINT_HOME=examples imprint mcp-server google-flights` |
272
+ | [**google-hotels**](examples/google-hotels) | Hotel search with star rating, guest scores, nightly + total prices | `IMPRINT_HOME=examples imprint mcp-server google-hotels` |
273
+ | [**discoverandgo**](examples/discoverandgo) | Authenticated booking via per-site credential store | `IMPRINT_HOME=examples imprint cron discoverandgo --once` |
274
+ | [**namecheap-domains**](examples/namecheap-domains) | Domain search with CRC32 URL signing reverse-engineered from JS, 5-endpoint chain with availability + aftermarket pricing | `IMPRINT_HOME=examples imprint mcp-server namecheap-domains` |
275
+ | [**echo**](examples/echo) | MCP smoke-test fixture (no network, no LLM) | `IMPRINT_HOME=examples imprint mcp-server echo` |
276
+
277
+ <br>
278
+
279
+ ## CLI reference
280
+
281
+ ```
282
+ imprint --help # all commands
283
+ imprint <command> --help # per-command options
284
+ ```
285
+
286
+ | | Commands |
287
+ |---|---|
288
+ | **Pipeline** | `teach` · `record` · `redact` · `generate` · `compile-playbook` · `emit` |
289
+ | **Runtime** | `cron` · `mcp-server` · `playbook` · `probe-backends` |
290
+ | **Credentials** | `credential set` · `credential list` · `credential export` · `credential import` · `credential migrate` |
291
+ | **Utilities** | `mcp` · `login` · `assemble` · `check` · `doctor` |
292
+
293
+ `teach`, `generate`, and `compile-playbook` accept `--provider <name>` to override the auto-detected LLM (see [Install](#install) for valid names and compile-agent support). `teach` and `generate` also take `--keep-test` to retain the agent-written `parser.test.ts` for debugging — it's deleted by default since it reads the gitignored redacted session via `$IMPRINT_SESSION_PATH` and isn't reproducible elsewhere. For multi-tool sites, use `imprint cron <site> --tool <toolName>` and `imprint probe-backends <site> --tool <toolName>` unless `--config` or `--out` points inside the target tool directory.
294
+
295
+ <br>
296
+
297
+ ## Docs
298
+
299
+ - [Getting Started](docs/getting-started.md) — full walkthrough
300
+ - [Integrations](docs/integrations.md) — per-platform setup
301
+ - [MCP Maintenance](docs/mcp-maintenance.md) — audit, disable, restore, and prune Imprint MCP state
302
+ - [Sharing Skills](docs/credential-sharing.md) — laptop ↔ OpenClaw / Hermes / remote-agent provisioning
303
+ - [Architecture](docs/architecture.md) — data flow and module map
304
+ - [Security](docs/security.md) — redaction, credential handling, what gets stored
305
+ - [Troubleshooting](docs/troubleshooting.md) — common failures and fixes
306
+ - [Decisions](docs/decisions.md) · [Glossary](docs/glossary.md) · [Capture Protocol](docs/capture-protocol.md) · [Playbook Debugging](docs/playbook-debugging.md) · [Notifications](docs/notifications.md)
307
+
308
+ <br>
309
+
310
+ ## Contributing
311
+
312
+ Conventional Commits enforced in CI. Run `bun run check` before submitting.
313
+
314
+ Good first contributions: replay backends, notification predicates, auth extractors, example sites, docs.
315
+
316
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for full guidelines.
317
+
318
+ <br>
319
+
320
+ ## License
321
+
322
+ [MIT](LICENSE)
@@ -0,0 +1,57 @@
1
+ # Discover & Go museum-pass booking
2
+
3
+ > Reserve a museum pass on the San Diego Public Library's Discover & Go service. Authenticated workflow; uses the per-site credential store populated by `imprint login`.
4
+
5
+ ## What this shows off
6
+
7
+ - **The `imprint login` flow.** Library cards are persistent; you log in once during recording and `imprint login` extracts the patron ID + cookies into `~/.config/imprint/credentials/discoverandgo.json`. Subsequent runs use those credentials without re-recording.
8
+ - **`${credential.X}` substitutions.** Workflow templates reference `${credential.patron_id}` directly; the runtime fills it from the credential store.
9
+ - **Plain `fetch` backend works** — Discover & Go has no bot detection, so this demo runs in ~200ms per call (no Playwright bootstrap, no DOM walk).
10
+
11
+ ## Run it
12
+
13
+ ```bash
14
+ # One-time: log in once via record, then mine credentials
15
+ imprint record discoverandgo --persist-profile --url https://sandiego.discoverandgo.net
16
+ # (drive a real reservation; narrate; /done when finished)
17
+
18
+ imprint login discoverandgo --from-session ~/.imprint/discoverandgo/sessions/<ts>.json
19
+
20
+ # Then any time you want to book:
21
+ imprint cron discoverandgo --once
22
+ ```
23
+
24
+ ## What you should see
25
+
26
+ ```
27
+ [imprint cron] config: examples/discoverandgo/book_discoverandgo_museum_pass/cron.json
28
+ [imprint cron] tool: book_discoverandgo_museum_pass (3 param(s))
29
+ [imprint cron] schedule: 0 0 * * *
30
+ [imprint cron] replayBackend: fetch
31
+ [imprint backend] trying fetch…
32
+ [imprint backend] fetch: OK in ~250ms
33
+ [imprint cron] OK in ~250ms via fetch: {"reservationID":...,"status":"confirmed",...}
34
+ ```
35
+
36
+ ## Files
37
+
38
+ | File | What |
39
+ |---|---|
40
+ | `workflow.json` | API workflow with `${credential.patron_id}` and `${param.offer_id}` substitutions |
41
+ | `index.ts` | Generated tool function |
42
+ | `cron.json` | Daily 0am tick (placeholder offer + date — edit to your real reservation) |
43
+
44
+ ## Tuning
45
+
46
+ - **Edit `cron.json`** with the actual `offer_id` (numeric attraction ID), `offer_date` (YYYY-MM-DD), and your `notification_email`.
47
+ - **Schedule** is daily; if you want to grab a pass the moment it opens (D&G releases new dates at midnight Pacific), tighten to `*/5 0 * * *` for 5-minute polling around midnight.
48
+
49
+ ## Notes
50
+
51
+ - Discover & Go's auth model is patron-ID + session cookies. The session cookie expires; re-run `imprint login` if you start seeing AUTH_EXPIRED.
52
+ - The workflow chains an `epass_server.php?method=Login` followed by the booking call. Generated `workflow.json` references both via the `${response[N].patronID}` extraction syntax.
53
+
54
+ ## Not in this demo
55
+
56
+ - Multi-attraction booking in one tick (one `cron.json` per attraction).
57
+ - Auto-renewal (passes are calendar-bound; renewal would mean picking the next available date).
@@ -0,0 +1,8 @@
1
+ {
2
+ "schedule": "0 0 * * *",
3
+ "params": {
4
+ "offer_id": 1175,
5
+ "offer_date": "1999-01-01",
6
+ "notification_email": "you@example.com"
7
+ }
8
+ }