transcripto 0.2.1__tar.gz → 0.3.0__tar.gz

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 (25) hide show
  1. {transcripto-0.2.1/transcripto.egg-info → transcripto-0.3.0}/PKG-INFO +185 -10
  2. {transcripto-0.2.1 → transcripto-0.3.0}/README.md +183 -8
  3. {transcripto-0.2.1 → transcripto-0.3.0}/pyproject.toml +3 -3
  4. transcripto-0.3.0/tests/test_jev.py +423 -0
  5. transcripto-0.3.0/tests/test_jev_findings.py +119 -0
  6. transcripto-0.3.0/tests/test_jev_invalid_responses.py +55 -0
  7. transcripto-0.3.0/tests/test_jev_preview.py +77 -0
  8. transcripto-0.3.0/tests/test_selected_context.py +62 -0
  9. {transcripto-0.2.1 → transcripto-0.3.0/transcripto.egg-info}/PKG-INFO +185 -10
  10. {transcripto-0.2.1 → transcripto-0.3.0}/transcripto.egg-info/SOURCES.txt +8 -0
  11. transcripto-0.3.0/transcripto.egg-info/top_level.txt +6 -0
  12. {transcripto-0.2.1 → transcripto-0.3.0}/transcripto.py +368 -65
  13. transcripto-0.3.0/transcripto_findings.py +87 -0
  14. transcripto-0.3.0/transcripto_jev.py +347 -0
  15. {transcripto-0.2.1 → transcripto-0.3.0}/transcripto_replay.py +29 -1
  16. transcripto-0.3.0/transcripto_selected.py +118 -0
  17. transcripto-0.2.1/transcripto.egg-info/top_level.txt +0 -3
  18. {transcripto-0.2.1 → transcripto-0.3.0}/LICENSE +0 -0
  19. {transcripto-0.2.1 → transcripto-0.3.0}/setup.cfg +0 -0
  20. {transcripto-0.2.1 → transcripto-0.3.0}/tests/test_harness_backfill.py +0 -0
  21. {transcripto-0.2.1 → transcripto-0.3.0}/tests/test_public_flow.py +0 -0
  22. {transcripto-0.2.1 → transcripto-0.3.0}/tests/test_replay.py +0 -0
  23. {transcripto-0.2.1 → transcripto-0.3.0}/transcripto.egg-info/dependency_links.txt +0 -0
  24. {transcripto-0.2.1 → transcripto-0.3.0}/transcripto.egg-info/entry_points.txt +0 -0
  25. {transcripto-0.2.1 → transcripto-0.3.0}/transcripto_core.py +0 -0
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: transcripto
3
- Version: 0.2.1
4
- Summary: Instant replay for coding agents. Inspect requests, tool calls, and recorded results across Claude Code, Codex, and Cursor. Local, stdlib-only.
3
+ Version: 0.3.0
4
+ Summary: Instant replay for coding agents. Inspect requests, tool calls, and recorded results across Claude Code, Codex, and Cursor. Local by default, stdlib-only.
5
5
  Author: Oscar Morke
6
6
  License: MIT
7
7
  Project-URL: Homepage, https://github.com/Morkeeth/transcripto
@@ -29,7 +29,7 @@ Claude Code · Codex · Cursor. Local files. No account. No runtime dependencies
29
29
  ## Start with something you remember saying
30
30
 
31
31
  ```sh
32
- uvx --from transcripto==0.2.1 transcripto ask "retry"
32
+ uvx --from transcripto==0.3.0 transcripto ask "retry"
33
33
  ```
34
34
 
35
35
  Replace `retry` with a word you remember using. `ask` searches messages identified
@@ -45,17 +45,17 @@ and its recorded work. This also works when search matches a word variant
45
45
  You can also search replay directly:
46
46
 
47
47
  ```sh
48
- uvx --from transcripto==0.2.1 transcripto replay "retry"
48
+ uvx --from transcripto==0.3.0 transcripto replay "retry"
49
49
 
50
50
  # Or open your latest human session:
51
- uvx --from transcripto==0.2.1 transcripto
51
+ uvx --from transcripto==0.3.0 transcripto
52
52
  ```
53
53
 
54
54
  Replay puts your request, tool calls and recorded results in order. Failed edits
55
55
  stay failed. Missing results stay unknown. Status describes tool execution,
56
56
  not whether the task was done correctly.
57
57
 
58
- Or install with `python3 -m pip install transcripto==0.2.1`, then run
58
+ Or install with `python3 -m pip install transcripto==0.3.0`, then run
59
59
  `transcripto ask "retry"`. Requires Python 3.9 or newer.
60
60
 
61
61
  ## Try the stranger flow without your transcripts
@@ -114,7 +114,7 @@ succeeded check, Cursor an unknown missing result.
114
114
  ### Offline flight card
115
115
 
116
116
  ```sh
117
- transcripto quickstart --wheel /absolute/path/to/transcripto-0.2.1-py3-none-any.whl
117
+ transcripto quickstart --wheel /absolute/path/to/transcripto-0.3.0-py3-none-any.whl
118
118
  ```
119
119
 
120
120
  Prints install, `import-lab`, search, and reopen commands for a built wheel
@@ -195,7 +195,7 @@ transcripto replay latest --share # counts + caveat; no prompts or pat
195
195
  ```
196
196
 
197
197
  `--share` is intentionally small. Full replay output and JSON contain your own
198
- words and local paths. The tool does not upload either.
198
+ words and local paths. Replay does not upload either.
199
199
 
200
200
  ## What each harness supports
201
201
 
@@ -270,10 +270,87 @@ agent caused them. Without a usable window, the commit fields are null.
270
270
 
271
271
  ## Privacy and limits
272
272
 
273
- The three runtime modules contain no network client, telemetry, account flow,
274
- or process execution. Package installation (`pip` or `uvx`) is a separate
273
+ The default commands process transcripts locally, without telemetry or an
274
+ account flow. The optional Jev detector below sends filtered typed text only
275
+ when explicitly selected. Package installation (`pip` or `uvx`) is a separate
275
276
  operation that may contact a package registry and write a package cache.
276
277
 
278
+ ### Optional network detector: `--detector jev`
279
+
280
+ `coach` and `export-run` can count corrections with TypeSafe Jev instead of the
281
+ local regex. This is the one path that sends text off the machine, and it runs
282
+ only when you pass the flag on that run. No environment variable or config file
283
+ turns it on. The code lives in its own module, `transcripto_jev.py`, which the
284
+ default path never imports.
285
+
286
+ ```sh
287
+ OPENROUTER_API_KEY=... transcripto coach --detector jev
288
+ ```
289
+
290
+ Before the first request it prints one line to stderr: how many typed turns it
291
+ may send, how many the privacy filter excluded, and the URL
292
+ (`https://openrouter.ai/api/alpha/decisions`, model `typesafe/jev-1.13`).
293
+ Only your typed turns are sent, at most 2,000 characters each, with the fixed
294
+ question. No separate path/session metadata, agent output or tool results are
295
+ sent. Typed text can still contain paths and private details the filter misses.
296
+ What OpenRouter and the model provider keep, and for how long, is set by their
297
+ terms. Transcripto does not verify it. Read those terms before the first send.
298
+
299
+ The privacy filter runs before any request is built:
300
+
301
+ - **Excluded, never sent:** a turn that names your account, cites a numbered
302
+ notes-folder path (two digits, a space, a folder name, a `.md` file), mentions a private topic (money,
303
+ finance, wallet, seed, key, password, token, salary, bank, journal, health,
304
+ family, whole words), or holds an email address or phone-like number.
305
+ - **Redacted, then sent:** API keys and tokens, AWS key ids, private-key blocks,
306
+ 40-hex `0x` addresses, and home directory paths.
307
+
308
+ Excluded turns and failed requests get no verdict. They are reported, never
309
+ filled in with the regex. The correction rate then uses the scored turns as its
310
+ denominator (`correction_rate_denominator: "jev.scored"`). JSON gains a `jev`
311
+ block with `sent`, `excluded`, `excluded_reasons`, `scored`, `errors`,
312
+ `cost_usd` and the served model.
313
+
314
+ Preview the privacy counts before choosing to send anything:
315
+
316
+ ```sh
317
+ transcripto coach --detector jev --jev-dry-run --json
318
+ transcripto export-run latest --detector jev --jev-dry-run
319
+ ```
320
+
321
+ This needs no API key and makes no requests, even with a key in the environment.
322
+ Both commands return the dedicated `transcripto.jev-privacy-preview/1` JSON
323
+ schema in dry-run mode (`coach` needs `--json`). The `jev` count block and null
324
+ correction fields stay available to existing count consumers. Ordinary coach
325
+ episodes and export session, file, tool and commit details are omitted; dry runs
326
+ do not inspect the project reflog or build an episode report.
327
+
328
+ It reports eligible turns, exclusions by reason, and redaction counts. It does
329
+ not print turn text, estimate cost, or produce correction verdicts. Eligibility
330
+ means the current filter permits a turn; it is not a guarantee that the text
331
+ contains no private information.
332
+
333
+ Options: `--jev-threshold` (default 0.30 on P(correction)), `--jev-max-usd`
334
+ (default 1.00, stops sending once reached), `--jev-batch` (default 1; larger
335
+ batches are cheaper but change the answers), `--jev-fallback-regex` (with no
336
+ key set, use the regex instead of exiting). A refused key (HTTP 401, 402, 403)
337
+ on the first request stops before any later batch. If a later request is refused,
338
+ completed verdicts are retained and no further wave starts.
339
+
340
+ The `eligible` count describes turns allowed by the filter; `sent` counts turns
341
+ submitted to transport, excluding later turns skipped by the spending stop.
342
+ Neither count proves that the remote service received a request successfully.
343
+
344
+ The spend limit must be finite and positive. Costs are reported after requests,
345
+ so requests already in flight can exceed the limit; it is not a provider-side
346
+ hard cap. If any request cost is missing or invalid, no further batch is sent
347
+ and the displayed cost is labelled an incomplete subtotal. Invalid probabilities
348
+ produce no verdict rather than a guessed correction label.
349
+
350
+ The default 0.30 comes from a local experiment on 185 turns, labelled by a
351
+ single model rater: agreement F1 about 0.77 to 0.83 against that rater, versus
352
+ 0.68 to 0.70 for the regex. That is agreement with a model, not accuracy.
353
+
277
354
  Replay and coach read transcripts without making an index. Search writes text
278
355
  and file metadata to `~/.trace/trace.db`. A new index directory is private;
279
356
  database and WAL files use mode `0600`. The index stays after the command exits.
@@ -313,3 +390,101 @@ index permissions, incremental search, and cross-harness retrieval.
313
390
 
314
391
  MIT. Open an issue with the **record shape** that fails, or a synthetic
315
392
  reproduction. Your real prompt text is not needed.
393
+
394
+ ### Inspect one session's Jev findings, then carry one candidate
395
+
396
+ Added in 0.3.0: a selected-session path.
397
+ Preview remains counts-only, offline and keyless:
398
+
399
+ ```sh
400
+ transcripto jev-findings /path/session.jsonl --detector jev --jev-dry-run
401
+ ```
402
+
403
+ Only when you choose to send that session's privacy-filtered typed turns:
404
+
405
+ ```sh
406
+ transcripto jev-findings /path/session.jsonl --detector jev \
407
+ --jev-max-usd 0.05 --output /your/private/findings.json
408
+ ```
409
+
410
+ The local report contains references, source/request hashes, exact lines,
411
+ probabilities, threshold, model metadata and observation time, without transcript
412
+ text. It marks candidate, not-candidate, excluded and unknown separately. Each
413
+ row prints its exact replay command. A candidate is a recorded model suggestion,
414
+ not a confirmed human correction. The serving-model hint is not a per-turn
415
+ model guarantee. The cap and provider/privacy limits above still apply.
416
+
417
+ After inspecting a candidate's request and recorded work, select its exact line:
418
+
419
+ ```sh
420
+ transcripto replay --findings /your/private/findings.json --line 3
421
+ transcripto handoff --findings /your/private/findings.json --line 3 \
422
+ --to-harness codex --output /your/private/candidate.json
423
+ transcripto receive-handoff /your/private/candidate.json --as-harness codex \
424
+ --output /your/private/receiver-brief.md
425
+ ```
426
+
427
+ Use the actual line shown by your report and choose a receiver different from
428
+ the source harness. Replay and handoff refuse a changed source, including changed
429
+ follow-up records around an unchanged request. Excluded, unknown and negative
430
+ findings cannot become candidate handoffs. A previously prepared packet whose
431
+ source changes remains historical; its receiver brief marks outcomes provisional.
432
+
433
+ The packet and receiver brief are private local files and contain selected
434
+ transcript text. They retain detector provenance, synthetic/test labels, and
435
+ pending human confirmation and receiver acknowledgement. They do not invoke an
436
+ agent or send a message. Reports, packets and briefs use mode `0600`; inspect
437
+ before sharing. `replay --share` remains counts-only.
438
+
439
+ ### Choose a local replay and author a handoff
440
+
441
+ A model report is optional. List metadata from an existing index, choose a source,
442
+ then explicitly permit local viewing of its requests and recorded tool outcomes:
443
+
444
+ ```sh
445
+ transcripto selected-context runs --cwd /your/repo
446
+ transcripto selected-context describe --source /your/session.jsonl
447
+ transcripto selected-context episodes --source /your/session.jsonl \
448
+ --accept-sha SHA256_FROM_DESCRIBE --consent
449
+ transcripto handoff --source /your/session.jsonl \
450
+ --accept-sha SHA256_FROM_DESCRIBE --line 3 \
451
+ --instruction 'Repair the selected output and verify the stated condition.' \
452
+ --consent --to-harness claude --output /your/private/packet.json
453
+ transcripto receive-handoff /your/private/packet.json --as-harness claude \
454
+ --output /your/private/brief.md
455
+ ```
456
+
457
+ `runs` accepts `--index /your/existing.sqlite`; it does not create or refresh an
458
+ index. It reads only metadata from at most the most recent 20,000 indexed records,
459
+ returning up to 20 runs by default (maximum 30). Suggestions are unbound: sharing a
460
+ working directory does not prove that a run produced your artifact. No title or
461
+ body is read by this query. SQLite may use locking sidecars. Choose a file explicitly
462
+ when the bounded index window has no suitable run.
463
+
464
+ `describe` reads bytes to compute identity without returning transcript text. The
465
+ consented replay returns at most the first 100 requests from one file of at most
466
+ 16 MiB; changed bytes or parsing warnings refuse replay. Authored handoffs retain
467
+ the original request, source hash, exact line and recorded outcomes. The new
468
+ instruction is explicit authorship for this handoff, not a detector verdict,
469
+ inferred human REDO or research label. Same-harness refusal and synthetic labels
470
+ remain. These commands prepare private local files; they do not invoke a receiver
471
+ or send a message. Review the full brief before giving it to another process.
472
+
473
+ ### Explicit authored continuation
474
+
475
+ `handoff` still requires a different receiver harness. For a separately chosen new
476
+ Claude session, the local producer can describe exactly one authored instruction:
477
+
478
+ ```sh
479
+ transcripto selected-context describe --source /path/to/session.jsonl
480
+ transcripto selected-context authored-continuation \
481
+ --source /path/to/session.jsonl --accept-sha SHA256_FROM_DESCRIBE \
482
+ --line 1 --instruction 'Add the missing label.' --consent
483
+ ```
484
+
485
+ This returns a typed local selection, not a handoff exception, detector verdict or
486
+ receiver invocation. Its source session UUID is derived from the consented bytes;
487
+ absent, malformed or mixed identities refuse. No filename/index fallback is used.
488
+ ZUP's separate new-session confirmation binds a fresh receiver UUID and actual
489
+ launch contract. New-session work is same-harness authored work, not independent
490
+ judgement or measured model improvement. Only explicitly selected context is carried.
@@ -11,7 +11,7 @@ Claude Code · Codex · Cursor. Local files. No account. No runtime dependencies
11
11
  ## Start with something you remember saying
12
12
 
13
13
  ```sh
14
- uvx --from transcripto==0.2.1 transcripto ask "retry"
14
+ uvx --from transcripto==0.3.0 transcripto ask "retry"
15
15
  ```
16
16
 
17
17
  Replace `retry` with a word you remember using. `ask` searches messages identified
@@ -27,17 +27,17 @@ and its recorded work. This also works when search matches a word variant
27
27
  You can also search replay directly:
28
28
 
29
29
  ```sh
30
- uvx --from transcripto==0.2.1 transcripto replay "retry"
30
+ uvx --from transcripto==0.3.0 transcripto replay "retry"
31
31
 
32
32
  # Or open your latest human session:
33
- uvx --from transcripto==0.2.1 transcripto
33
+ uvx --from transcripto==0.3.0 transcripto
34
34
  ```
35
35
 
36
36
  Replay puts your request, tool calls and recorded results in order. Failed edits
37
37
  stay failed. Missing results stay unknown. Status describes tool execution,
38
38
  not whether the task was done correctly.
39
39
 
40
- Or install with `python3 -m pip install transcripto==0.2.1`, then run
40
+ Or install with `python3 -m pip install transcripto==0.3.0`, then run
41
41
  `transcripto ask "retry"`. Requires Python 3.9 or newer.
42
42
 
43
43
  ## Try the stranger flow without your transcripts
@@ -96,7 +96,7 @@ succeeded check, Cursor an unknown missing result.
96
96
  ### Offline flight card
97
97
 
98
98
  ```sh
99
- transcripto quickstart --wheel /absolute/path/to/transcripto-0.2.1-py3-none-any.whl
99
+ transcripto quickstart --wheel /absolute/path/to/transcripto-0.3.0-py3-none-any.whl
100
100
  ```
101
101
 
102
102
  Prints install, `import-lab`, search, and reopen commands for a built wheel
@@ -177,7 +177,7 @@ transcripto replay latest --share # counts + caveat; no prompts or pat
177
177
  ```
178
178
 
179
179
  `--share` is intentionally small. Full replay output and JSON contain your own
180
- words and local paths. The tool does not upload either.
180
+ words and local paths. Replay does not upload either.
181
181
 
182
182
  ## What each harness supports
183
183
 
@@ -252,10 +252,87 @@ agent caused them. Without a usable window, the commit fields are null.
252
252
 
253
253
  ## Privacy and limits
254
254
 
255
- The three runtime modules contain no network client, telemetry, account flow,
256
- or process execution. Package installation (`pip` or `uvx`) is a separate
255
+ The default commands process transcripts locally, without telemetry or an
256
+ account flow. The optional Jev detector below sends filtered typed text only
257
+ when explicitly selected. Package installation (`pip` or `uvx`) is a separate
257
258
  operation that may contact a package registry and write a package cache.
258
259
 
260
+ ### Optional network detector: `--detector jev`
261
+
262
+ `coach` and `export-run` can count corrections with TypeSafe Jev instead of the
263
+ local regex. This is the one path that sends text off the machine, and it runs
264
+ only when you pass the flag on that run. No environment variable or config file
265
+ turns it on. The code lives in its own module, `transcripto_jev.py`, which the
266
+ default path never imports.
267
+
268
+ ```sh
269
+ OPENROUTER_API_KEY=... transcripto coach --detector jev
270
+ ```
271
+
272
+ Before the first request it prints one line to stderr: how many typed turns it
273
+ may send, how many the privacy filter excluded, and the URL
274
+ (`https://openrouter.ai/api/alpha/decisions`, model `typesafe/jev-1.13`).
275
+ Only your typed turns are sent, at most 2,000 characters each, with the fixed
276
+ question. No separate path/session metadata, agent output or tool results are
277
+ sent. Typed text can still contain paths and private details the filter misses.
278
+ What OpenRouter and the model provider keep, and for how long, is set by their
279
+ terms. Transcripto does not verify it. Read those terms before the first send.
280
+
281
+ The privacy filter runs before any request is built:
282
+
283
+ - **Excluded, never sent:** a turn that names your account, cites a numbered
284
+ notes-folder path (two digits, a space, a folder name, a `.md` file), mentions a private topic (money,
285
+ finance, wallet, seed, key, password, token, salary, bank, journal, health,
286
+ family, whole words), or holds an email address or phone-like number.
287
+ - **Redacted, then sent:** API keys and tokens, AWS key ids, private-key blocks,
288
+ 40-hex `0x` addresses, and home directory paths.
289
+
290
+ Excluded turns and failed requests get no verdict. They are reported, never
291
+ filled in with the regex. The correction rate then uses the scored turns as its
292
+ denominator (`correction_rate_denominator: "jev.scored"`). JSON gains a `jev`
293
+ block with `sent`, `excluded`, `excluded_reasons`, `scored`, `errors`,
294
+ `cost_usd` and the served model.
295
+
296
+ Preview the privacy counts before choosing to send anything:
297
+
298
+ ```sh
299
+ transcripto coach --detector jev --jev-dry-run --json
300
+ transcripto export-run latest --detector jev --jev-dry-run
301
+ ```
302
+
303
+ This needs no API key and makes no requests, even with a key in the environment.
304
+ Both commands return the dedicated `transcripto.jev-privacy-preview/1` JSON
305
+ schema in dry-run mode (`coach` needs `--json`). The `jev` count block and null
306
+ correction fields stay available to existing count consumers. Ordinary coach
307
+ episodes and export session, file, tool and commit details are omitted; dry runs
308
+ do not inspect the project reflog or build an episode report.
309
+
310
+ It reports eligible turns, exclusions by reason, and redaction counts. It does
311
+ not print turn text, estimate cost, or produce correction verdicts. Eligibility
312
+ means the current filter permits a turn; it is not a guarantee that the text
313
+ contains no private information.
314
+
315
+ Options: `--jev-threshold` (default 0.30 on P(correction)), `--jev-max-usd`
316
+ (default 1.00, stops sending once reached), `--jev-batch` (default 1; larger
317
+ batches are cheaper but change the answers), `--jev-fallback-regex` (with no
318
+ key set, use the regex instead of exiting). A refused key (HTTP 401, 402, 403)
319
+ on the first request stops before any later batch. If a later request is refused,
320
+ completed verdicts are retained and no further wave starts.
321
+
322
+ The `eligible` count describes turns allowed by the filter; `sent` counts turns
323
+ submitted to transport, excluding later turns skipped by the spending stop.
324
+ Neither count proves that the remote service received a request successfully.
325
+
326
+ The spend limit must be finite and positive. Costs are reported after requests,
327
+ so requests already in flight can exceed the limit; it is not a provider-side
328
+ hard cap. If any request cost is missing or invalid, no further batch is sent
329
+ and the displayed cost is labelled an incomplete subtotal. Invalid probabilities
330
+ produce no verdict rather than a guessed correction label.
331
+
332
+ The default 0.30 comes from a local experiment on 185 turns, labelled by a
333
+ single model rater: agreement F1 about 0.77 to 0.83 against that rater, versus
334
+ 0.68 to 0.70 for the regex. That is agreement with a model, not accuracy.
335
+
259
336
  Replay and coach read transcripts without making an index. Search writes text
260
337
  and file metadata to `~/.trace/trace.db`. A new index directory is private;
261
338
  database and WAL files use mode `0600`. The index stays after the command exits.
@@ -295,3 +372,101 @@ index permissions, incremental search, and cross-harness retrieval.
295
372
 
296
373
  MIT. Open an issue with the **record shape** that fails, or a synthetic
297
374
  reproduction. Your real prompt text is not needed.
375
+
376
+ ### Inspect one session's Jev findings, then carry one candidate
377
+
378
+ Added in 0.3.0: a selected-session path.
379
+ Preview remains counts-only, offline and keyless:
380
+
381
+ ```sh
382
+ transcripto jev-findings /path/session.jsonl --detector jev --jev-dry-run
383
+ ```
384
+
385
+ Only when you choose to send that session's privacy-filtered typed turns:
386
+
387
+ ```sh
388
+ transcripto jev-findings /path/session.jsonl --detector jev \
389
+ --jev-max-usd 0.05 --output /your/private/findings.json
390
+ ```
391
+
392
+ The local report contains references, source/request hashes, exact lines,
393
+ probabilities, threshold, model metadata and observation time, without transcript
394
+ text. It marks candidate, not-candidate, excluded and unknown separately. Each
395
+ row prints its exact replay command. A candidate is a recorded model suggestion,
396
+ not a confirmed human correction. The serving-model hint is not a per-turn
397
+ model guarantee. The cap and provider/privacy limits above still apply.
398
+
399
+ After inspecting a candidate's request and recorded work, select its exact line:
400
+
401
+ ```sh
402
+ transcripto replay --findings /your/private/findings.json --line 3
403
+ transcripto handoff --findings /your/private/findings.json --line 3 \
404
+ --to-harness codex --output /your/private/candidate.json
405
+ transcripto receive-handoff /your/private/candidate.json --as-harness codex \
406
+ --output /your/private/receiver-brief.md
407
+ ```
408
+
409
+ Use the actual line shown by your report and choose a receiver different from
410
+ the source harness. Replay and handoff refuse a changed source, including changed
411
+ follow-up records around an unchanged request. Excluded, unknown and negative
412
+ findings cannot become candidate handoffs. A previously prepared packet whose
413
+ source changes remains historical; its receiver brief marks outcomes provisional.
414
+
415
+ The packet and receiver brief are private local files and contain selected
416
+ transcript text. They retain detector provenance, synthetic/test labels, and
417
+ pending human confirmation and receiver acknowledgement. They do not invoke an
418
+ agent or send a message. Reports, packets and briefs use mode `0600`; inspect
419
+ before sharing. `replay --share` remains counts-only.
420
+
421
+ ### Choose a local replay and author a handoff
422
+
423
+ A model report is optional. List metadata from an existing index, choose a source,
424
+ then explicitly permit local viewing of its requests and recorded tool outcomes:
425
+
426
+ ```sh
427
+ transcripto selected-context runs --cwd /your/repo
428
+ transcripto selected-context describe --source /your/session.jsonl
429
+ transcripto selected-context episodes --source /your/session.jsonl \
430
+ --accept-sha SHA256_FROM_DESCRIBE --consent
431
+ transcripto handoff --source /your/session.jsonl \
432
+ --accept-sha SHA256_FROM_DESCRIBE --line 3 \
433
+ --instruction 'Repair the selected output and verify the stated condition.' \
434
+ --consent --to-harness claude --output /your/private/packet.json
435
+ transcripto receive-handoff /your/private/packet.json --as-harness claude \
436
+ --output /your/private/brief.md
437
+ ```
438
+
439
+ `runs` accepts `--index /your/existing.sqlite`; it does not create or refresh an
440
+ index. It reads only metadata from at most the most recent 20,000 indexed records,
441
+ returning up to 20 runs by default (maximum 30). Suggestions are unbound: sharing a
442
+ working directory does not prove that a run produced your artifact. No title or
443
+ body is read by this query. SQLite may use locking sidecars. Choose a file explicitly
444
+ when the bounded index window has no suitable run.
445
+
446
+ `describe` reads bytes to compute identity without returning transcript text. The
447
+ consented replay returns at most the first 100 requests from one file of at most
448
+ 16 MiB; changed bytes or parsing warnings refuse replay. Authored handoffs retain
449
+ the original request, source hash, exact line and recorded outcomes. The new
450
+ instruction is explicit authorship for this handoff, not a detector verdict,
451
+ inferred human REDO or research label. Same-harness refusal and synthetic labels
452
+ remain. These commands prepare private local files; they do not invoke a receiver
453
+ or send a message. Review the full brief before giving it to another process.
454
+
455
+ ### Explicit authored continuation
456
+
457
+ `handoff` still requires a different receiver harness. For a separately chosen new
458
+ Claude session, the local producer can describe exactly one authored instruction:
459
+
460
+ ```sh
461
+ transcripto selected-context describe --source /path/to/session.jsonl
462
+ transcripto selected-context authored-continuation \
463
+ --source /path/to/session.jsonl --accept-sha SHA256_FROM_DESCRIBE \
464
+ --line 1 --instruction 'Add the missing label.' --consent
465
+ ```
466
+
467
+ This returns a typed local selection, not a handoff exception, detector verdict or
468
+ receiver invocation. Its source session UUID is derived from the consented bytes;
469
+ absent, malformed or mixed identities refuse. No filename/index fallback is used.
470
+ ZUP's separate new-session confirmation binds a fresh receiver UUID and actual
471
+ launch contract. New-session work is same-harness authored work, not independent
472
+ judgement or measured model improvement. Only explicitly selected context is carried.
@@ -4,8 +4,8 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "transcripto"
7
- version = "0.2.1"
8
- description = "Instant replay for coding agents. Inspect requests, tool calls, and recorded results across Claude Code, Codex, and Cursor. Local, stdlib-only."
7
+ version = "0.3.0"
8
+ description = "Instant replay for coding agents. Inspect requests, tool calls, and recorded results across Claude Code, Codex, and Cursor. Local by default, stdlib-only."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
11
11
  license = { text = "MIT" }
@@ -28,4 +28,4 @@ Source = "https://github.com/Morkeeth/transcripto"
28
28
  transcripto = "transcripto:main"
29
29
 
30
30
  [tool.setuptools]
31
- py-modules = ["transcripto", "transcripto_core", "transcripto_replay"]
31
+ py-modules = ["transcripto", "transcripto_core", "transcripto_replay", "transcripto_jev", "transcripto_findings", "transcripto_selected"]