@nurix/etna 0.15.6 → 0.15.8

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 (88) hide show
  1. package/bin/etna.js +64 -13
  2. package/data/harness-index.json +7 -5
  3. package/data/harnesses/code/CLAUDE.md +3 -7
  4. package/data/harnesses/code/agents/harness-manager.md +4 -4
  5. package/data/harnesses/code/agents/maintenance.md +1 -1
  6. package/data/harnesses/code/harness.json +4 -3
  7. package/data/harnesses/code/hooks/hooks.json +3 -17
  8. package/data/harnesses/code/hooks/prompt-recall.js +157 -0
  9. package/data/harnesses/code/hooks/session-reflect.js +283 -0
  10. package/data/harnesses/code/skills/distiller/SKILL.md +62 -60
  11. package/data/harnesses/code/skills/distiller/references/docs-mode.md +21 -21
  12. package/data/harnesses/code/skills/distiller/references/method.md +41 -41
  13. package/data/harnesses/code/skills/documentation/references/templates.md +20 -27
  14. package/data/harnesses/code-fable/CLAUDE.md +138 -0
  15. package/data/harnesses/code-fable/agents/brainstorm.md +35 -0
  16. package/data/harnesses/code-fable/agents/change-review.md +249 -0
  17. package/data/harnesses/code-fable/agents/harness-manager.md +193 -0
  18. package/data/harnesses/code-fable/agents/maintenance.md +123 -0
  19. package/data/harnesses/code-fable/agents/performance-review.md +218 -0
  20. package/data/harnesses/code-fable/agents/spec-mode.md +56 -0
  21. package/data/harnesses/code-fable/harness.json +7 -0
  22. package/data/harnesses/code-fable/hooks/hooks.json +27 -0
  23. package/data/harnesses/code-fable/hooks/lib/redact.js +37 -0
  24. package/data/harnesses/code-fable/hooks/prompt-recall.js +157 -0
  25. package/data/harnesses/code-fable/hooks/session-reflect.js +283 -0
  26. package/data/harnesses/code-fable/rules/general.md +96 -0
  27. package/data/harnesses/code-fable/rules/nomenclature.md +34 -0
  28. package/data/harnesses/code-fable/skills/boundary/SKILL.md +262 -0
  29. package/data/harnesses/code-fable/skills/boundary/references/boundary-taxonomy.md +734 -0
  30. package/data/harnesses/code-fable/skills/brainstorm/README.md +136 -0
  31. package/data/harnesses/code-fable/skills/brainstorm/SKILL.md +135 -0
  32. package/data/harnesses/code-fable/skills/brainstorm/harvest.md +26 -0
  33. package/data/harnesses/code-fable/skills/brainstorm/templates/backlog.md +39 -0
  34. package/data/harnesses/code-fable/skills/brainstorm/templates/build.md +37 -0
  35. package/data/harnesses/code-fable/skills/brainstorm/templates/decisions.md +29 -0
  36. package/data/harnesses/code-fable/skills/brainstorm/templates/doctrine.md +31 -0
  37. package/data/harnesses/code-fable/skills/brainstorm/templates/domain-model.md +25 -0
  38. package/data/harnesses/code-fable/skills/brainstorm/templates/glossary.md +19 -0
  39. package/data/harnesses/code-fable/skills/brainstorm/templates/milestones.md +43 -0
  40. package/data/harnesses/code-fable/skills/brainstorm/templates/non-goals.md +21 -0
  41. package/data/harnesses/code-fable/skills/brainstorm/templates/plan-doc.md +61 -0
  42. package/data/harnesses/code-fable/skills/brainstorm/templates/questions.md +35 -0
  43. package/data/harnesses/code-fable/skills/brainstorm/templates/references.md +28 -0
  44. package/data/harnesses/code-fable/skills/brainstorm/templates/rejected.md +29 -0
  45. package/data/harnesses/code-fable/skills/brainstorm/templates/state.md +8 -0
  46. package/data/harnesses/code-fable/skills/brainstorm/templates/tech.md +23 -0
  47. package/data/harnesses/code-fable/skills/brainstorm/templates/thesis.md +21 -0
  48. package/data/harnesses/code-fable/skills/distiller/SKILL.md +219 -0
  49. package/data/harnesses/code-fable/skills/distiller/references/docs-mode.md +526 -0
  50. package/data/harnesses/code-fable/skills/distiller/references/method.md +166 -0
  51. package/data/harnesses/code-fable/skills/documentation/SKILL.md +127 -0
  52. package/data/harnesses/code-fable/skills/documentation/references/examples.md +193 -0
  53. package/data/harnesses/code-fable/skills/documentation/references/style-guide.md +288 -0
  54. package/data/harnesses/code-fable/skills/documentation/references/templates.md +942 -0
  55. package/data/harnesses/code-fable/skills/workflow-mapper/SKILL.md +430 -0
  56. package/data/harnesses/code-fable/skills/workflow-mapper/references/patterns.md +214 -0
  57. package/data/harnesses/discover/CLAUDE.md +180 -0
  58. package/data/harnesses/{re → discover}/agents/api.md +3 -3
  59. package/data/harnesses/{re → discover}/agents/codebase.md +3 -3
  60. package/data/harnesses/{re → discover}/agents/community.md +3 -3
  61. package/data/harnesses/{re → discover}/agents/deployed-client-bundle.md +21 -15
  62. package/data/harnesses/{re → discover}/agents/distribution-artifacts.md +13 -12
  63. package/data/harnesses/{re → discover}/agents/docs.md +3 -3
  64. package/data/harnesses/{re → discover}/agents/infra-backend-fingerprint.md +3 -3
  65. package/data/harnesses/{re → discover}/agents/packages.md +3 -3
  66. package/data/harnesses/{re → discover}/agents/session.md +29 -11
  67. package/data/harnesses/{re → discover}/agents/website.md +3 -3
  68. package/data/harnesses/{re → discover}/agents/wire-capture.md +14 -10
  69. package/data/harnesses/discover/harness.json +7 -0
  70. package/data/harnesses/{re/rules/re-discovery.md → discover/rules/discovery.md} +86 -17
  71. package/data/harnesses/{re/rules/re-evaluation.md → discover/rules/evaluation.md} +40 -4
  72. package/data/harnesses/discover/rules/ingestion.md +551 -0
  73. package/data/harnesses/discover/rules/self-correction.md +177 -0
  74. package/data/harnesses/discover/rules/tradecraft.md +532 -0
  75. package/data/harnesses/hr/CLAUDE.md +91 -0
  76. package/data/harnesses/hr/harness.json +7 -0
  77. package/data/harnesses/hr/skills/interview-eval/SKILL.md +118 -0
  78. package/data/harnesses/hr/skills/interview-eval/TEMPLATE.md +124 -0
  79. package/data/harnesses/hr/skills/interview-eval/extract_session.py +418 -0
  80. package/data/harnesses/hr/skills/interview-eval/rubric.md +219 -0
  81. package/data/harnesses/kb-agi/harness.json +1 -0
  82. package/package.json +1 -1
  83. package/data/harnesses/code/hooks/post-commit.js +0 -136
  84. package/data/harnesses/code/hooks/post-tool-failure.js +0 -136
  85. package/data/harnesses/code/hooks/session-stop.js +0 -207
  86. package/data/harnesses/re/CLAUDE.md +0 -146
  87. package/data/harnesses/re/harness.json +0 -6
  88. package/data/harnesses/re/rules/re-ingestion.md +0 -327
@@ -1,327 +0,0 @@
1
- # Ingestion Contract — Dump Shape · Provenance · Ethics · Session Playbook
2
-
3
- The reference knowledge for **Ingestion** (`re` harness, Mode 2). Every dimension dump obeys the
4
- contract in §1–8 so (a) the **evaluation** mode can rely on a stable shape and weight each claim by
5
- *how it was obtained*, and (b) a future agent can reproduce or extend any dump. §9 carries the
6
- deepest, gated dimension's method — the logged-in browser-session playbook — which the `session`
7
- agent follows.
8
-
9
- This contract generalizes the source playbook's three-format contract (`captures/*.md` narrative +
10
- `raw/*.json` verbatim + `curls.md`) to *any* dimension.
11
-
12
- > **Contract style = "lighter".** Provenance ("how it was dumped") lives in the
13
- > **`_summary.md` frontmatter**, not a separate `manifest.yaml`. There is no parallel YAML
14
- > machine-spine — everything stays markdown-with-frontmatter. Evaluation reads the frontmatter
15
- > to weight claims; self-correction reads it to detect under-delivery.
16
-
17
- ---
18
-
19
- ## 1. Folder layout
20
-
21
- ```
22
- research/<target>/dimensions/<dimension>/
23
- ├── _summary.md ← decoded narrative + provenance frontmatter (human + machine read this)
24
- └── raw/ ← verbatim artifacts (the reproducer reads these)
25
- ```
26
-
27
- Richer dimensions inherit the playbook contract (extra files, same `_summary.md` provenance):
28
- - **session**: `dimensions/session/{_summary.md, captures/p*.md, raw/*.json, curls.md}`
29
- - **wire-capture**: `dimensions/wire-capture/{_summary.md, captures/wire-narrative.md, raw/flows.json, curls.md}`
30
-
31
- ---
32
-
33
- ## 2. `_summary.md` — required shape (with provenance frontmatter)
34
-
35
- ```markdown
36
- ---
37
- dimension: <codebase|docs|packages|api|website|community|session|deployed-client-bundle|infra-backend-fingerprint|wire-capture|distribution-artifacts>
38
- target: <slug>
39
- status: complete | partial | blocked
40
- # --- provenance (the "how it was dumped" layer evaluation weights on) ---
41
- access_grade_used: <source:full | runtime:reachable | auth:have-login | presence:rich | ...>
42
- method: <the ACTUAL extraction method — see §3 vocabulary>
43
- completeness_pct: <0-100, honest self-estimate of reachable surface captured>
44
- confidence: high | medium | low # how much to TRUST what was captured (see §3)
45
- captured_at: <YYYY-MM-DD>
46
- sources: [<urls / paths actually consulted>]
47
- gaps: [<structured — each is a thing evaluation must NOT treat as covered>]
48
- ---
49
-
50
- # <Target> — <Dimension> dump
51
-
52
- ## Method
53
- Exactly what was done, which tools, what was skipped and why. (The prose behind the frontmatter `method`.)
54
-
55
- ## Findings
56
- Ordered, concrete observations — real values (package names, versions, endpoint paths, file
57
- paths, page URLs, prices). Tables liberally. The load-bearing section.
58
-
59
- ## Inferences
60
- What the findings imply. Mark inference vs. fact.
61
-
62
- ## Open questions
63
- What couldn't be captured and why. Never fabricate to fill a gap.
64
-
65
- ## Artifacts
66
- Index of `raw/` files, one line each.
67
- ```
68
-
69
- Keep `status` and `confidence` honest — they drive the entire evaluation weighting.
70
-
71
- ---
72
-
73
- ## 3. Method & confidence vocabulary (drives evaluation weighting)
74
-
75
- `method` is one of: `clone-and-map`, `source-map-reassembly`, `registry-metadata`,
76
- `openapi-verbatim`, `graphql-introspection`, `crawl-clip`, `docs-reconstructed`,
77
- `bundle-string-mine`, `dns-ct-fingerprint`, `wire-tap-browser`, `wire-har`, `wire-mitmproxy`,
78
- `binary-extract` (asar/apk/crx), `session-playbook`, `inferred`.
79
-
80
- **Confidence is a function of method** (evaluation relies on this mapping):
81
- - **high** — verbatim machine artifacts: `openapi-verbatim`, `graphql-introspection`, `registry-metadata`, `clone-and-map`, `binary-extract`.
82
- - **medium** — `crawl-clip`, `docs-reconstructed`, `bundle-string-mine`, `dns-ct-fingerprint`, `wire-har`.
83
- - **low** — `inferred`, `session-playbook` Pass-1-only, `wire-tap-browser` shapes-only, any wire-drift observation without a spec.
84
-
85
- ---
86
-
87
- ## 4. `raw/*` — required shape
88
-
89
- Structured captures (API responses, registry metadata, schemas) → JSON with a `_meta` header:
90
- ```json
91
- {
92
- "_meta": { "source": "...", "captured_at": "YYYY-MM-DD", "kind": "...", "byte_length": 0, "redactions": ["field → <REDACTED:...>"] },
93
- "body": { /* verbatim, PII + secrets redacted */ },
94
- "_decoded": { "field": "meaning + observed values" },
95
- "_observation": "optional — what's load-bearing"
96
- }
97
- ```
98
- Prose captures (doc/marketing pages, structure maps, catalogs) → markdown with a metadata line:
99
- `<!-- source: <url-or-path> · captured_at: YYYY-MM-DD · method: <method> -->`
100
-
101
- **One file per logical artifact**, named by what it is (`endpoint-catalog.md`, `react-exports.md`,
102
- `pricing.md`, `structure-map.md`).
103
-
104
- ---
105
-
106
- ## 5. Size discipline — reduce, don't dump
107
-
108
- Large artifacts (a 3 MB bundle, a 5 MB response, a 700-page sitemap) are **digested**, not pasted:
109
- the schema/shape, enum distributions, one redacted representative sample, counts. A `raw/` file is
110
- readable, not a memory dump. Set `digested: true` context in the artifact's `_meta`.
111
-
112
- ---
113
-
114
- ## 6. The shared-surface seam rule (bundle ↔ session ↔ wire-capture)
115
-
116
- `deployed-client-bundle` (static unauth SPA), `session` (authenticated browser runtime), and
117
- `wire-capture` (non-browser client) can all surface the same **API path catalog** and **feature
118
- flags**. To keep them consumable instead of triplicated:
119
-
120
- - Use **one canonical artifact name** across all three: `raw/api-path-catalog.md` and
121
- `raw/feature-flags.md`, each row carrying a `source: bundle | session | wire` column.
122
- - Evaluation owns the **three-way diff** (static-declared vs browser-observed vs nonbrowser-observed)
123
- in `data-model-api-surface.md`. A path that appears in `bundle` but never in `session`/`wire` is a
124
- dormant/unshipped route — a finding, not noise.
125
-
126
- > **Published API ≠ the app's own API.** A product's developer/REST/MCP surface (`api`/`docs`/`packages`
127
- > dims) is frequently *not* the API its own app runs on (`session`/`bundle` dims) — different protocol,
128
- > host, and operation set. Always diff the two: operations the app uses but the public API omits, **and**
129
- > public operations the app never calls, are both findings. The published surface is the integration
130
- > story; the runtime surface is the real architecture.
131
-
132
- ---
133
-
134
- ## 7. Ethics & redaction (non-negotiable — binds EVERY dimension)
135
-
136
- Carried from the source playbook (`setup.md` §6). Violating them voids the work.
137
-
138
- 1. **Never enter credentials.** The user signs into any logged-in surface beforehand.
139
- 2. **Storage: shape, not values.** No raw cookies/tokens/JWT-signatures. Decode JWT *structure* with identity claims (`sub`,`email`,`phone`,`user_id`,`uid`,`sid`) redacted.
140
- 3. **Never save secrets.** Before any `raw/` write, redact every credential-shaped field → `<REDACTED:...>` + log in `_meta.redactions`. Field patterns: `api_key`,`*_secret`,`client_secret`,`webhook_secret`,`signing_*`,`password`,`private_key`,`access_token`/`refresh_token` in bodies, vendor-named secrets. Value patterns: `sk_live_…`/`pk_live_…` (Stripe), `sk-…` (OpenAI), `xox[bp]-…` (Slack), `AKIA…` (AWS), `gh[ps]_…` (GitHub), `AIza…` (Google), `eyJ…` (JWT), opaque base64 ≥32 chars in a credential field. Over-redact when unsure.
141
- 4. **Confirm before state changes** — anything that creates state, costs money, or is visible to others (even a draft toggle). State the exact action + estimated cost.
142
- 5. **No destructive actions.** Document the absence; move on.
143
- 6. **No bypassing safety harnesses** — redact, never evade.
144
- 7. **No exfiltration.** Captures stay local under `research/<target>/`.
145
- 8. **Respect TOS & robots.** For spec-writing / integration / competitive analysis — not credential theft, rate-limit bypass, or scraping.
146
- 9. **One browser-driving dimension at a time.** Chrome MCP is a shared singleton. Only the gated `session`/`wire-capture` dimensions drive the browser; parallel non-browser dumpers use WebFetch/curl, or — if a page genuinely needs a real browser — create their **own** tab and never touch the session tab. Never run two browser-driving dumpers concurrently.
147
- 10. **Verify an absence before asserting it.** A "host is NXDOMAIN / dimension is absent / endpoint 404s everywhere" claim that would *contradict another dimension* must be re-checked by a **second method** (alternate resolver, direct HTTP probe, second source) before it is written as fact. A single-resolver/single-probe negative is recorded as *tentative*, never as a cross-dimension directive. (An HTTP 4xx/5xx means the host **resolves** — present, not absent.)
148
- 11. **Bounded live-token use (read-only, in-page only).** To fill a Pass-1 capture gap you MAY read the live token from its store and replay a **read-only** request with it — *only* if the token is used **in-page / in-process only**, is **never written to `raw/`, never returned, never logged**, and the replay changes no state. This is the single permitted touch of a live credential; rules 2–3 (shape-not-values, never-save-secrets) still bind everything written to disk.
149
-
150
- ### 7.1 wire-capture & active-interception ethics (the strictest tier)
151
-
152
- The `wire-capture` dimension climbs a **3-rung ladder, lowest privilege first**, and records the
153
- chosen rung in `_meta`:
154
-
155
- 1. **Browser network tap (default, unauth).** Chrome `read_network_requests` + the in-page
156
- fetch/XHR interceptor on the **public** surface only. Capture request/response *shapes*; redact
157
- in the wrapper before disk. No login. → `method: wire-tap-browser`.
158
- 2. **HAR export.** Export DevTools HAR of the unauth SPA's XHRs, digest to an endpoint catalog,
159
- scrub `Authorization`/`Cookie`/secret-shaped values. → `method: wire-har`.
160
- 3. **mitmproxy / intercepting proxy — GATED, opt-in, user-run.** ONLY first-party traffic the
161
- **user owns** (their own desktop/mobile/CLI client), ONLY with explicit chat authorization, ONLY
162
- TOS-checked. The harness NEVER stands up a proxy against a third party's infra unattended; the
163
- *user* installs the CA and routes their client — the agent only ingests exported flows. →
164
- `method: wire-mitmproxy`. Same explicit-authorization loop as session Pass-2.
165
-
166
- > Wireshark / packet capture is explicitly **not** used: for HTTPS it yields only TLS ciphertext,
167
- > and a packet sweep of a third party is the bright line this harness will not cross.
168
-
169
- ### 7.2 distribution-artifacts ethics
170
- Downloading a public binary (CRX/`.asar`/`.ipa`/`.apk`) and reading its manifest/strings is fine.
171
- But binary **decompilation** can cross from "inspect" to "reverse-engineer in violation of EULA":
172
- the agent reads the artifact's own license/EULA first and records a restrictive one as an Open
173
- question rather than silently decompiling.
174
-
175
- ---
176
-
177
- ## 8. Completeness check
178
- A dump is complete when: `_summary.md` exists with full provenance frontmatter + honest `status`;
179
- every Finding is backed by a `raw/` artifact or inline value; `raw/` artifacts have `_meta` +
180
- decoding (large ones digested); redaction pass run; `gaps` recorded (never fabricated).
181
-
182
- **Summary-first + bounded, visible fan-out (never go silent long enough to look dead).** Write a
183
- `status: partial` `_summary.md` with whatever is mined so far **before** any long-tail fetch loop
184
- (downloading many chunks, crawling many pages, deep pagination), then enrich it in place and flip to
185
- `complete`. **Bound** every fan-out — cap it by count / total bytes / wall-time (e.g. ≤40 items or
186
- ≤90 s) and record the remainder as a `gap` rather than fetching exhaustively; emit a progress note per
187
- batch. A dumper that fetches everything before writing anything can run many times longer than its
188
- siblings and read as hung to the orchestrator, forcing a needless salvage. Partial-but-finalized beats
189
- complete-but-silent.
190
-
191
- ---
192
-
193
- ## 9. The session dimension — logged-in browser-session playbook
194
-
195
- The method for the **session** dimension: reverse-engineering the *authenticated runtime* of a
196
- product by driving it through a browser (Chrome MCP) and instrumenting it. It produces a
197
- section-by-section understanding of a product's wire protocol, auth, and state model **without
198
- source-code access**. The `session` agent follows this section.
199
-
200
- This is the deepest and most sensitive dimension. The ethics in §7 above bind hardest here.
201
-
202
- ### 9.1 Prerequisites (verify before anything else — all three non-negotiable)
203
-
204
- | # | Precondition | How to verify |
205
- |---|--------------|---------------|
206
- | 1 | Target is **pre-logged-in** in Chrome | open the target URL in the connected tab → an authenticated surface (a dashboard, not a sign-in page). The agent never enters credentials. |
207
- | 2 | **Claude Chrome extension** installed | `mcp__claude-in-chrome__tabs_context_mcp` returns live tabs |
208
- | 3 | **Chrome CDP** connected | the same call returns stable tab IDs |
209
-
210
- If any fails, return `blocked` naming the missing precondition.
211
-
212
- ### 9.2 The three-pass strategy
213
-
214
- A single linear sweep wastes context on things you can read for free and wastes credits on
215
- actions whose response shape you could infer. Use three passes.
216
-
217
- **Pass 1 — read-only mining (no money, no state change).** If the user already has data (a
218
- project, conversation, account, order), mine it first. Hit every list/state/history endpoint with
219
- the existing token; capture verbatim bodies. This yields ~70% of the spec for free. Mine, by role:
220
- identity (`/me`, `/account`, `/workspaces`), list (the canonical taxonomy), single-resource state
221
- (server-injected vs client-sent fields), history/event-log (a whole trajectory in one call),
222
- runtime/preview state, per-resource billing, account billing, feature flags/cohort, **the account's
223
- `entitlements`/`permissions` arrays** (the single richest data-model artifact — `entitlements`/`features`
224
- enumerate every gated feature *including ones your plan hides*; `permissions` are CRUD-verbs-per-entity,
225
- so the verb set enumerates the domain entity set — `X_CREATE/VIEW/EDIT/DELETE` ⇒ entity `X`; mine these
226
- first), integration
227
- catalog (`/mcp/`, `/integrations/`), and schema/capabilities (`/openapi.json`, `/.well-known/*`,
228
- `/page-metadata`).
229
-
230
- **Pass 2 — fresh-run validation (with explicit cost/state-change confirmation).** Only after
231
- Pass 1, and only with explicit user OK stating the exact action + cheapest mode + estimated cost.
232
- Catches what Pass 1 can't: the submit/write request body, live state-machine transitions, the
233
- completion event, server-side resolution of shorthand, ID/slug-generation, the real iteration
234
- endpoint, and the full realtime event catalog. **Legitimate to skip** if the user opts out — leave
235
- write-side shapes as open questions; never fabricate them.
236
-
237
- **Pass 3 — synthesis.** Walk the captures, pull each finding into the dimension's `_summary.md`,
238
- note the cleverest design choices, defaults imposed, performance characteristics, and open
239
- questions.
240
-
241
- ### 9.3 The P0 → P6 phases
242
-
243
- The same phases apply whether the target is an AI builder, analytics dashboard, CRM, or collab tool:
244
-
245
- | Phase | Focus |
246
- |-------|-------|
247
- | **P0 Surface** | routes, bundles, storage shape, the API host(s), the auth tell; build the **coverage checklist** from any route/op catalog a sibling declared (§9.4) |
248
- | **P1 Auth** | token type + issuer + storage location + refresh path; tenancy model; **disambiguate the transport by omission** (replay one authed read with each credential mechanism dropped) — and never test auth with a schema-only field |
249
- | **P2 Core action** | the primary write — the submit/create body and its server resolution |
250
- | **P3 Streaming** | the realtime transport (WS / SSE / WebChannel / Pusher / none) + event catalog; **fingerprint binary frames by signature, never log them as opaque** (§9.4) |
251
- | **P4 Runtime/state** | sandbox/preview/build/deploy state; the live result surface |
252
- | **P5 Iteration** | the follow-up/edit endpoint (often surprisingly named) + any auto-iteration loop |
253
- | **P6 Synthesis** | reconcile into the dimension's `_summary.md` + `captures/` + `curls.md` |
254
-
255
- ### 9.4 Runtime taps (Pass-1 instrumentation, run in-page)
256
-
257
- > **Install the in-page interceptor FIRST, then move section-to-section WITHOUT a full reload.**
258
- > CDP `read_network_requests` is unreliable for an already-loaded single-page app: it starts tracking
259
- > only when first called and silently misses requests already in flight or served from cache (seen on a
260
- > real run where only a third-party analytics beacon was captured while the app's own API calls went
261
- > unseen). Treat it as a *supplement*; the in-page interceptor is the primary capture. A full-page
262
- > `navigate` wipes the interceptor, so traverse the app using whatever it exposes — **clicking in-app
263
- > nav works on any stack**; or call the client router if one is reachable (`history.pushState`+`popstate`,
264
- > React Router / Vue Router / Angular Router, or a globally-exposed router such as `window.next.router`
265
- > on Next.js). The principle is framework-agnostic; the specific call is just whatever that app ships.
266
-
267
- - **WebSocket / EventSource / fetch+XHR interceptors** — wrap the constructors/methods to log
268
- URLs, frames, and bodies (shapes, not secrets — redact in the wrapper before anything reaches
269
- disk). Add a `SCRUB(value)` step inside the fetch wrapper so credentials never reach the harness.
270
- **Never log a binary frame as opaque `<binary>`.** Any realtime/streaming/collab layer (token
271
- streams, CRDT/OT edits, presence, telemetry, game or market state) may ship `ArrayBuffer`/`Blob`
272
- frames; for each *distinct* frame capture its **byte-length + a hex dump of the first ~16 bytes** —
273
- enough to fingerprint the wire format (protobuf, MessagePack, CBOR, Yjs/CRDT, gRPC-web, or a
274
- text/topic-prefixed channel protocol) without recording content. **Decode the signature as ASCII
275
- first** — many "binary" protocols are framed text (STOMP, Phoenix, Centrifugo, a `+topic` channel
276
- prefix), so a legible prefix names the protocol in one step before a binary-codec guess. The frame
277
- *signature* is the finding; the payload is not.
278
- - **Storage shape inspector** — enumerate localStorage / sessionStorage / cookies / IndexedDB
279
- **key names + lengths**, never raw values.
280
- - **JWT decoder** — decode the token *structure* (alg, claim names, exp) with identity claims
281
- (`sub`, `email`, `phone`, `user_id`, `uid`, `sid`) redacted.
282
- - **Auth-channel disambiguation.** Token *location* is itself a tell: not in localStorage ⇒ an httpOnly
283
- cookie **or** an SDK store (IndexedDB — Firebase/Auth0/Supabase/Cognito keep tokens there, which is why
284
- a "no JWT in localStorage" result is a finding, not a dead end). Determine the *required* transport by
285
- **omission**: replay one harmless authed read — using a field that needs the authed context (`viewer`/
286
- `me`), **never** a schema-only field (GraphQL `__typename`, a health route) that resolves
287
- unauthenticated — with each candidate credential dropped (cookie-only, then header-only); whichever
288
- response comes back unauthorized names the channel the app actually requires.
289
- - If a realtime SDK is loaded (Pusher, Ably, Socket.IO, Centrifugo, Phoenix, …), bind a global listener
290
- to capture the event/channel catalog.
291
- - **Third-party-SDK fingerprint** (cross-checks `infra-backend-fingerprint`). Storage key names + the
292
- network host list name the embedded vendor stack — auth (Firebase/Auth0), flags (LaunchDarkly/Statsig),
293
- support (Intercom/Zendesk/Ada), analytics (Segment/Amplitude/Datadog), payments (Stripe). Record them;
294
- they corroborate the sub-processor list *independently* (a different dimension → promotes confidence).
295
- - **Drive op coverage from any catalog a sibling declared.** If `deployed-client-bundle` (or `api`/`docs`)
296
- recovered a declared **route / endpoint / operation catalog** — a REST path table, a GraphQL operation
297
- set, an RPC/tool method list — consume it as a **coverage checklist**: walk the routes/actions that
298
- trigger the un-observed entries so the declared-vs-observed diff (§6) reflects a real walk, not just the
299
- landing page.
300
-
301
- ### 9.5 The capture contract (richer than a standard dimension dump)
302
-
303
- Under `research/<target>/dimensions/session/`:
304
-
305
- - **`captures/p*.md`** — per-phase narrative for the human: frontmatter (title, summary, scope,
306
- status), **Method** (taps run, actions taken), **Findings** (concrete values — URLs, fields,
307
- status codes), **Inferences**, **Diff vs reference**, **Open questions**. Decoded, opinionated;
308
- don't paste raw bodies here.
309
- - **`raw/*.json`** — verbatim endpoint captures for the reproducer: a `_meta` header
310
- (endpoint, auth-shape, captured_at, status, byte_length, redactions) + `body` (PII + secrets
311
- redacted) + `_decoded_fields`. Digest bodies > 50 KB into a structured summary.
312
- - **`curls.md`** — reproducible curl per endpoint, the auth model documented, a variables block,
313
- and an endpoint-catalog table.
314
- - **`captures/screens/`** (recommended) — one annotated screenshot per primary surface (each major nav
315
- section), plus a short tour recording if useful. The fastest "what does it actually do" artifact for a
316
- human reader, complementing the wire teardown — and the place the visual product map lives. Redact any
317
- visible PII before saving.
318
- - **`_summary.md`** — the standard dimension bridge file (provenance frontmatter per §2) pointing
319
- into the above, so Evaluation treats session like any other dimension. `method: session-playbook`,
320
- `confidence: low` for Pass-1-only/inferred.
321
-
322
- ### 9.6 Session ethics (binds hardest here — see §7 above)
323
-
324
- Never enter credentials; storage shape not values; redact every secret **inside the tap wrapper**
325
- before it reaches disk; **confirm before any Pass-2 state change or cost** (exact action + exact
326
- cost); no destructive actions; no bypassing the harness (redact, never evade); captures stay local;
327
- respect TOS. The provenance/redaction rules in §1–8 apply to everything written here.