linersh 0.5.0 → 0.5.1

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 (74) hide show
  1. package/bin/liner.js +37 -0
  2. package/cli-update-docs/ABOUT.md +69 -0
  3. package/cli-update-docs/CURATION.md +261 -0
  4. package/cli-update-docs/JOB-STORY-MIGRATION.md +99 -0
  5. package/cli-update-docs/JTBD-MASTER-PROMPT-ABOUT.md +133 -0
  6. package/cli-update-docs/JTBD-MASTER-PROMPT.md +147 -0
  7. package/cli-update-docs/MIXTAPE-FORMAT.md +398 -0
  8. package/cli-update-docs/PLATFORM.md +210 -0
  9. package/cli-update-docs/README.md +107 -0
  10. package/cli-update-docs/SKILL.md +244 -0
  11. package/cli-update-docs/TUI-BACKLOG.md +196 -0
  12. package/cli-update-docs/curator-notes.md +84 -0
  13. package/cli-update-docs/quality-check-tests.md +196 -0
  14. package/cli-update-docs/source-finding-tactics.md +99 -0
  15. package/cli-update-docs/source-quality-hierarchy.md +130 -0
  16. package/cli-update-docs/synthesis-guidance.md +133 -0
  17. package/dist/App.js +29 -12
  18. package/dist/App.js.map +1 -1
  19. package/dist/agents/detect.js +14 -4
  20. package/dist/agents/detect.js.map +1 -1
  21. package/dist/colors.js +48 -21
  22. package/dist/colors.js.map +1 -1
  23. package/dist/components/Header.js +5 -5
  24. package/dist/components/Header.js.map +1 -1
  25. package/dist/components/KeyHints.js +9 -2
  26. package/dist/components/KeyHints.js.map +1 -1
  27. package/dist/components/LabeledBox.js +2 -2
  28. package/dist/components/LabeledBox.js.map +1 -1
  29. package/dist/components/NextSteps.js +2 -2
  30. package/dist/components/NextSteps.js.map +1 -1
  31. package/dist/open-folder.js +28 -0
  32. package/dist/open-folder.js.map +1 -0
  33. package/dist/screens/AgentSetup.js +12 -12
  34. package/dist/screens/AgentSetup.js.map +1 -1
  35. package/dist/screens/BootSplash.js +30 -15
  36. package/dist/screens/BootSplash.js.map +1 -1
  37. package/dist/screens/CompileView.js +21 -12
  38. package/dist/screens/CompileView.js.map +1 -1
  39. package/dist/screens/FramingConfirmReview.js +6 -6
  40. package/dist/screens/FramingConfirmReview.js.map +1 -1
  41. package/dist/screens/Gate1Review.js +4 -4
  42. package/dist/screens/Gate1Review.js.map +1 -1
  43. package/dist/screens/Gate2Review.js +4 -4
  44. package/dist/screens/Gate2Review.js.map +1 -1
  45. package/dist/screens/ImportPrompt.js +3 -3
  46. package/dist/screens/ImportPrompt.js.map +1 -1
  47. package/dist/screens/LocalFilePicker.js +5 -5
  48. package/dist/screens/LocalFilePicker.js.map +1 -1
  49. package/dist/screens/NewMixtapeWizard.js +14 -14
  50. package/dist/screens/NewMixtapeWizard.js.map +1 -1
  51. package/dist/screens/PhaseRunner.js +52 -43
  52. package/dist/screens/PhaseRunner.js.map +1 -1
  53. package/dist/screens/ProcessManifest.js +4 -4
  54. package/dist/screens/ProcessManifest.js.map +1 -1
  55. package/dist/screens/ProjectHub.js +31 -25
  56. package/dist/screens/ProjectHub.js.map +1 -1
  57. package/dist/screens/SourceModal.js +2 -2
  58. package/dist/screens/SourceModal.js.map +1 -1
  59. package/dist/screens/TapeBrowser.js +10 -9
  60. package/dist/screens/TapeBrowser.js.map +1 -1
  61. package/dist/screens/TapeDraftReview.js +17 -17
  62. package/dist/screens/TapeDraftReview.js.map +1 -1
  63. package/dist/screens/TapeEditor.js +5 -5
  64. package/dist/screens/TapeEditor.js.map +1 -1
  65. package/dist/screens/cassette-art.js +21 -21
  66. package/package.json +5 -4
  67. package/dist/browser-support.js +0 -62
  68. package/dist/browser-support.js.map +0 -1
  69. package/dist/screens/BrowserSetup.js +0 -181
  70. package/dist/screens/BrowserSetup.js.map +0 -1
  71. package/dist/screens/NewProjectPrompt.js +0 -66
  72. package/dist/screens/NewProjectPrompt.js.map +0 -1
  73. package/dist/screens/Settings.js +0 -72
  74. package/dist/screens/Settings.js.map +0 -1
@@ -0,0 +1,196 @@
1
+ # TUI backlog
2
+
3
+ Running list of work deferred from earlier slices. Newest at the top of each section. When something ships, move it to **Done** with the date.
4
+
5
+ ---
6
+
7
+ ## Lessons from cli-writer-6 (2026-05-22)
8
+
9
+ Captured after comparing cli-writer-3 (v0.3 methodology, 15 sources) and cli-writer-6 (v0.4 methodology, 23 sources) on the same JTBD lineage. The v0.4 methodology changes are visibly paying off (sharper JTBD, task-oriented sections, source-kind chips, framing-gap audit firing). The items below are the next layer of methodology, prompt, and UX tightening suggested by what the artifact shows.
10
+
11
+ ### Synthesis-level — generative rules deserve explicit slots
12
+
13
+ - **Require a "Generative rules" or "If you remember nothing else…" subsection in the synthesis.** v3 had five top-level operational principles (predictability, density, help-is-doc, errors-deserve-care, streams-have-meaning). v6 has the equivalent material but it's dispersed inside paragraphs, harder for the consuming AI to load as decision rules. A prompt directive in Phase 6 to surface ~5 operational generative rules — phrased as imperatives — would close this gap without changing source selection. Worked example to embed in `synthesis-guidance.md`: "Channel discipline: stdout for data, stderr for human, exit codes mean what they say. This single rule resolves most 'should I print this?' questions."
14
+ - **The "stances this corpus takes" section was great — keep it as a required header.** v6 introduced it explicitly; v3 did similar work under "Contested questions" but less decisively. Make it canonical in the synthesis template.
15
+
16
+ ### Curator notes — chip the kind into the note line
17
+
18
+ - **Render the source `kind` chip inline at the top of each curator note in MIXTAPE.md.** Today the kind is one of many bullet attributes; consuming AIs don't always carry it forward when they load a single source file. Prepending `**[principle]**` or similar to the first line of the note ("**[principle]** Read for the framing — …") would make the weighting impossible to miss when the AI loads only `sources/NN-foo.md` for a deep read. Render-only change in `output/mixtape.py`.
19
+
20
+ ### Methodology — unverified content and the verification re-check
21
+
22
+ - **Auto re-run the perspectives audit at compile time when previously-unverified sources became verified.** v6 kept two YouTube sources (Küber, Pinsker) with curator notes acknowledging transcripts were unfetched at evaluation. By compile time `yt-dlp` produced real transcripts, but the perspectives audit's "unverified does not count" verdict from Phase 5 was never revisited. A `liner verify <folder>` command (or a compile-time hook) could re-check whether unverified perspective slots are now verifiable, and flag the gap closing as a soft signal back to the curator.
23
+ - **Curator-added sources should default to a sensible kind and prompt for it before commit.** The new `[+] add own` flow leaves `kind` unset. Either default to `principle` (the synthesis-writing default per `prompts.ts`) or open a four-button kind picker after URL submission. Cheap UX add; saves the curator a tape.yaml edit pass.
24
+
25
+ ### Quality of evaluation — note-quality smell test
26
+
27
+ - **Add a Phase 5 sub-check: "is each curator note doing real work?"** Notes that read as filler (e.g., "Skim a few command pages to calibrate density and rhythm") aren't earning weight in the consuming AI's loading decisions. A simple rubric — note must (a) cite what to read for, (b) name the bar it sets, (c) flag one limitation or scope boundary — would force the agent to deepen thin notes before shipping. Belongs in `quality-check-tests.md` as a 6th test.
28
+
29
+ ### Compile-time fetcher chain
30
+
31
+ - **Wayback Machine as a fetcher tier between Playwright and the agent-summary fallback.** Cheap, no tokens, returns raw HTML the trafilatura extractor can use — full article instead of summary. Right move when richer fallback content matters for production-quality mixtapes. Discussed in the v6 session; deferred at curator's request because the agent-summary fallback is sufficient for current scope.
32
+ - **Per-source actions on compile failure** (`[d]` drop, `[o]` open in browser, `[j]` retry with render: js). Surfaces recourse on a failed source instead of forcing the curator to edit tape.yaml. Currently the only recourse is "rerun all," which is misleadingly named — see DONE entry below where the hint was tightened to "retry failed."
33
+ - **Failure detail capture.** When the web handler raises, capture the HTTP code, content-type, first ~500 bytes of body, and a category (`paywall`, `not_found`, `forbidden`, `js_required`, `tls`, `network`, `unknown`). Display on the failed source line. 80% of "why did this fail" questions resolved with no LLM call.
34
+
35
+ ### Surface improvements
36
+
37
+ - **Surface Test 5 (kind-balance) outcomes visibly in the TUI.** Make the curator see the distribution at Phase 5 completion — a `4 prescription · 6 principle · 2 example · 0 reference` line in the gate2/quality-check review screen, with the zero column flagged in yellow if undefended. Lightweight implementation: parse `working/04-quality-checks.md` for the Test 5 section and render in the existing Gate2Review surface.
38
+ - **Perspectives audit display.** Same idea — show the curator the named perspectives + stance/concerns coverage as a structured list, not just buried in markdown.
39
+ - **Library cross-reference at JTBD time (deferred — needs library).** When the library exists, surface "mixtapes in your library that match these JTBD keywords" during Phase 1 so the curator can opt to start from a related one and preserve sources/framings that worked.
40
+
41
+ ---
42
+
43
+ ## Up next (functional — needed to "get everything working")
44
+
45
+ ### Token cost surfaces (2026-05-27)
46
+
47
+ - **The `$X.XXX` cost figure is probably fake — verify or remove it (2026-05-28).** PhaseRunner's summary line shows a dollar cost (e.g. `$2.525` on a session-limit run). We don't have real per-token pricing for either agent: Claude Code and Codex runs go through the user's *subscription*, not metered API billing, so a dollar figure is misleading at best and wrong at worst. Decide: (a) drop the dollar figure entirely and show only token counts, or (b) make it a clearly-labeled *estimate* with a configurable rate. Whichever — the fix must land in **both** agent adapters (`src/agents/` Claude parser + Codex parser) and any summary surface that renders cost, so the two don't diverge. Until then, leaning toward removing the dollar amount, since "tokens spent" is real and "dollars spent" is invented.
48
+ - **Cumulative token counter for the whole run.** Today the PhaseRunner shows live tokens for the current phase via the `tokens` event. There is no roll-up at the mixtape level — a curator finishes a 7-phase run with no idea what it cost in total. Aggregate token usage across all `.liner-runs/*.jsonl` entries for a project and surface a `Total tokens` line on the ProjectHub (or its own row in the ProcessManifest screen, which already aggregates similar data). Cheap because the aggregator already exists.
49
+ - **Pre-flight token estimate before kicking off a phase.** Before pressing Enter to run Phase 2 (or any agent-eligible phase), the user should see a "this phase typically costs ~X tokens" hint so they know roughly what they're committing to. Implementation idea: instrument the next several real runs to record actual per-phase token counts in `.liner-runs/`, then compute a rolling median per phase. After ~3–5 sample mixtapes, the median per-phase + per-mode (quick vs. methodology) becomes a useful baseline that ships with the package; later it should update dynamically from the user's own history. Open question: show the estimate per phase, or as a single "whole mixtape ≈ N tokens" number at wizard exit — both are useful, the latter is the bigger conversion lever.
50
+
51
+ ### Consistent quit key across all screens (2026-05-28)
52
+
53
+ - **`q` is overloaded; there's no uniform quit affordance.** Audit of `input === "q"`: TapeBrowser → quit (`ink.exit()`); ProjectHub / ProcessManifest / CompileView → go-back / cancel (esc-equivalent); Gate2Review → open quality-checks in `$EDITOR`; BootSplash → quit (added 2026-05-28); everywhere else → unbound. So a user can't rely on `q` meaning "quit." Decide a convention and apply it everywhere: either (a) `q` = quit globally — then reassign Gate2Review's quality-checks to another key and drop the redundant q-as-back on Hub/Manifest/Compile (esc already does back); or (b) keep `q` per-screen and document Ctrl-C as the universal quit. Note: Ctrl-C *already* quits from every screen (Ink's `exitOnCtrlC` default), so the functional ability to quit exists today — this is about a discoverable, consistent affordance. Text-input screens (wizard, source modal, tape editor, import prompt) can't take a bare `q` regardless — it types into the field — so those rely on esc-then-quit or Ctrl-C no matter which convention wins.
54
+
55
+ ### Resume/state redesign — summary-checklist landing for ProjectHub (2026-05-28, for 0.5.2)
56
+
57
+ **Problem.** Opening an already-finished mixtape drops the curator on the optional Phase 8 (empirical test), framed identically to a required step ("▶ current · press enter to run the empirical test"). A complete, compiled, usable mixtape looks the same as one stuck mid-flow — you can't tell whether it finished. The model treats "all 8 phases done" as the only notion of complete and silently parks you on the optional one. The real "done" milestone — **compiled & usable** (`MIXTAPE.md` written) — is never surfaced.
58
+
59
+ **Decision (confirmed with curator 2026-05-28):** replace the hub's dual focus-card / TOC modes with **one summary-checklist landing**. Drop the single-phase focus card entirely.
60
+
61
+ **Layout:**
62
+
63
+ ```
64
+ ▶ liner <title> · v0.5.x
65
+ <folder> · <jtbd…>
66
+
67
+ ┌ status ─────────────────────────────────────────────┐
68
+ │ ✓ Ready to use — compiled · 25 sources │
69
+ │ Optional: empirical test not run │
70
+ └──────────────────────────────────────────────────────┘
71
+
72
+ 1 ✓ Framing
73
+ 2 ✓ Candidate discovery
74
+ 4 ✓ Evaluation
75
+ 5 ✓ Quality checks
76
+ 6 ✓ Synthesis
77
+ 7 ✓ Assembly · compiled
78
+ 8 ○ Empirical test optional
79
+
80
+ next · You're done. Share it, open the folder, or run the optional test.
81
+
82
+ ↑↓ select enter run selected c compile s share o open folder e edit esc back
83
+ ```
84
+
85
+ **Status box — three states** (the load-bearing new element):
86
+ - `○ Not started` → next: Framing
87
+ - `◐ In progress — N of 7 steps done` → next: `<phase name>`
88
+ - `✓ Ready to use — compiled · N sources` → the optional empirical test is called out as *optional*, never as a nag
89
+
90
+ Use the existing `coreMethodologyComplete(progress)` (Phases 1–7 + compile) for the "Ready to use" line and `everythingComplete(progress)` (incl. Phase 8) for "fully complete incl. optional." Source count + compiled-or-not comes from `MIXTAPE.md` / `sources/` on disk (computePhases already reads artifacts).
91
+
92
+ **Behavior:**
93
+ - This summary is the default landing — no more landing on the optional phase as "current."
94
+ - ↑↓ selects a phase; a detail line shows the selected phase's info; **enter acts on the selected phase** (run agent / open gate / compile on the compile row / open draft review on assembly).
95
+ - Collapse the current focus + TOC dual-mode into this one view; the `l` toggle goes away. `currentIndex` still marks the recommended-next phase (highlighted), but selection is free.
96
+ - Surface the "compiled" milestone explicitly (on the Assembly row + in the status box) so "done" is unmistakable.
97
+ - Keep future-phase lockout (can't run a phase before its predecessors) — the sequential rule already exists.
98
+
99
+ **Touch points:** `src/screens/ProjectHub.tsx` (rewrite the view layer; keep the input/dispatch logic), `src/phases.ts` (already has the completion helpers; may add a `summaryStatus(progress, folder)` helper returning the status-line text + state). No change to the progress-cursor model — this is presentation.
100
+
101
+ ### PhaseRunner scrollback laddering — alt-screen wasn't enough (2026-05-28)
102
+
103
+ - **The 0.5.1 alt-screen fix doesn't hold on every terminal.** Wrapping the TUI launch in alt-screen mode (`\x1b[?1049h`) was supposed to kill the stacked-header artifact globally. Confirmed still reproducing in 0.5.1 on the curator's terminal: a Phase 3 run that hit the agent session limit left 10+ duplicated `liner · phase 3 — Evaluation · v0.5.1` headers stacked, growing as the screen re-rendered. Root cause: some terminals (this one included) preserve scrollback *even in the alternate buffer*, so alt-screen alone doesn't prevent the ladder — and when Ink's render output exceeds terminal height, the overflow scrolls regardless of buffer. The real fix is to stop PhaseRunner's render height from exceeding the viewport: wrap the variable-height regions (streamed final-response box, the tool-calls list which grows to 48+ entries) in fixed-height `<Box>` with `overflow="hidden"`, showing the tail. Same technique as the wizard Transcript stabilization but applied to PhaseRunner's running / done / failed views. Keep alt-screen (it helps on terminals that honor it); add height-capping as the actual guarantee. Edge case that surfaced this: **the session-limit failure state** — `× exited with code 1` + "You've hit your session limit" + a 48-tool-call list is one of the tallest renders the TUI produces.
104
+
105
+ ### Agent unavailability needs a hard error, not a hang (2026-05-27)
106
+
107
+ - **Detect agent CLI auth/quota failure and fail loudly.** Observed 2026-05-27: starting a run with Codex while the underlying Codex subscription had expired produced a silent hang — the agent process was launched, didn't emit any stream events, didn't error out, and the TUI sat on the running spinner indefinitely. Same class of failure applies to revoked API keys, expired auth tokens, network blocked, model deprecated. The TUI needs a watchdog that, if no `assistant` / `tool_use` / `tokens` event arrives within ~15s of process start *and* stderr stays empty, surfaces a clear "couldn't reach <agent> — check auth/subscription" error with `[r] retry` and `[a] switch agent` actions. Likely fix is in the agent adapter (`src/agents/`), not the runner. Also worth a one-time pre-flight `--version` or `/whoami`-style call on agent selection so dead auth is caught before the curator commits to a phase.
108
+
109
+ ### Slice 3 — agent integration polish
110
+
111
+ - **Background-banner concurrent runs.** Current architecture cancels the run when the user navigates away from PhaseRunner. If we want to support "leave the agent working while I edit elsewhere," we need to lift run state to app context and add a hub banner. Not blocking — pause-and-resume is a real product question, not just an implementation one.
112
+
113
+ ### Phase 8 path
114
+
115
+ - **Empirical-test capture.** Phase 8 currently just opens a template in `$EDITOR`. Could offer an interactive flow that runs the same question through two Claude sessions (with and without `MIXTAPE.md`) and writes the comparison.
116
+
117
+ ### CLI affordances the TUI might want
118
+
119
+ - **`liner status <folder> --json`** — phase-by-phase completion report from the CLI so the TUI doesn't duplicate filesystem checks. Optional; current detection works.
120
+ - **`liner init` flags** — `--mode`, `--jtbd`, `--title`, `--description`, `--curator` so the wizard doesn't post-process the scaffolded `tape.yaml`. Optional; current writeTape works.
121
+
122
+ ---
123
+
124
+ ## Visual polish (optional, after functional work is done)
125
+
126
+ - **Per-screen "what Enter does" description line + uniform navbar (2026-05-28).** Supersedes the earlier "highlight the primary action in KeyHints" idea, which was tried in 0.5.1 and reverted. The problem it exposed: PhaseRunner (and other screens) already render a *descriptive* call-to-action line above the navbar ("enter → resume from where the agent stopped (no re-fetching)") AND the navbar repeats `enter try again` — two Enter instructions competing for attention. Better model: (1) every screen gets a single description line above the navbar, in HEADING/purple, that spells out what the primary action (Enter) does in plain language; (2) the `KeyHints` navbar below stays uniform dim-green reference — no per-binding highlight. The description carries the "do this next" weight; the navbar is just the key map. Audit all 15 KeyHints callers: some already have a description line (PhaseRunner, gates), some don't (wizard input steps show the step question but not an Enter-outcome line). Make it consistent. This keeps one loud thing per screen instead of two.
127
+ - **Boot logo screen.** Use `ink-gradient` + `ink-big-text` for a real branded splash on first paint. ~40KB extra deps.
128
+ - **Animated phase-transition flash.** When a phase moves to `complete` (status change detected on refresh), briefly flash the row with a pulsing background color.
129
+ - **Notification fade-out.** Right now notifications time out at 3500ms with a hard cut. A 200ms fade would feel more polished.
130
+ - **Custom mode picker.** Replace the current arrow + cyan-text mode chooser in the wizard with background-color chips (`[ Quick ]` / `[ Methodology ]`) styled like the brand chip.
131
+ - **Pre-selected default in multi-choice pickers (2026-05-27).** Every inline multi-choice picker (agent selection, mode chooser, future "kind" picker, anywhere the user must pick one of N options) should pre-highlight the recommended/first option so the user can press Enter immediately to take the default. Confused users press Enter blindly; making the default safe rather than ambiguous turns that into the right behavior instead of a 25%-correct gamble. Navigation: ← / → cycles (or ↑ / ↓ if vertical layout), Enter accepts. Do **not** add Space as a second accept key — Space is reserved for toggle semantics (multi-select checkboxes) and overloading it in single-select widgets breaks the convention users carry in from other TUIs. The visual treatment should mirror what the navbar primary-action fix does: chosen option full-color + bold, others dimmed. Apply consistently across `NewMixtapeWizard.tsx`, `AgentSetup.tsx`, and anywhere `select`-style prompts live today. Implementation idea: a shared `<Picker>` component that takes `options` + `defaultIndex` and emits the chosen value.
132
+ - **Inline help overlay.** `?` key opens a modal listing every binding on the current screen. Grows in value as the keymap expands.
133
+ - **measureElement-based responsive sizing.** For artifact previews, table widths in Gate UIs, etc. The hub uses percentage widths already; this would tighten the rest.
134
+ - **Per-screen color discipline pass.** The skill says magenta = "highlights / special items." We use it for header brand and step chips; could pick one home and be more consistent.
135
+ - **`ux-intro-outro` outro.** On `q` exit, show a one-line outro (Clack-style). The chip in the header is the intro; we don't currently have an outro.
136
+
137
+ ---
138
+
139
+ ## Quality / hygiene
140
+
141
+ - **`ink-link` for clickable URLs** in error messages (e.g., the "missing agent" install hints).
142
+ - **Smoke test that mounts the TUI** — vitest currently only covers `yaml-io`. Could use `ink-testing-library` to render-test the wizard and hub.
143
+ - **Width-aware truncation.** Several places do `truncate(s, 70)` with a hardcoded width. Should derive from terminal columns.
144
+ - **Header version pin.** The version constant in `Header.tsx` is hardcoded `"0.3.0"`. Wire it to `package.json` at build time (or via a `--define` in tsc) so it can't go stale.
145
+ - **NO_COLOR + FORCE_COLOR test.** Ink respects these; we should manually verify on a real `NO_COLOR=1` run that the brand chip degrades gracefully.
146
+
147
+ ---
148
+
149
+ ## Project-level (not TUI but related)
150
+
151
+ The TUI work isn't blocking on these, but they shape what we build next.
152
+
153
+ - Curating-mixtapes skill bundle second pass (worked examples for the five companion files).
154
+ - Methodology-mode validation: a planned side-by-side CLI vs. TUI design comparison.
155
+ - First library entry (Cowork synthesis → methodology-mode mixtape folder).
156
+ - MCP server scaffolding.
157
+ - **Marketing site: state the agent requirement up front (2026-05-28).** The landing page must make clear Liner drives the curation agent through the user's *own* Claude Code or Codex subscription — it doesn't bundle or pay for inference. This is both an honesty point (no surprise "why isn't it working" when a user has neither) and a positioning point (it rides the subscription they already pay for). Put it near the install/requirements section: "Bring your own agent — works with your Claude Code or Codex subscription." Lives in `marketing/site/`.
158
+
159
+ ---
160
+
161
+ ## Done
162
+
163
+ - 2026-05-28 — **Scrollback laddering killed globally via terminal alt-screen mode.** Replaces the partial 2026-05-19 PhaseRunner compaction fix and the 0.5.1 wizard Transcript padding hack with one architectural fix in `bin/liner.js`: wrap the TUI launch in `\x1b[?1049h` / `\x1b[?1049l` (terminal alt-screen). No scrollback in the alt buffer = no stacked-header artifact, regardless of how variable-height a screen is. Cleanup handlers cover normal exit, SIGINT, SIGTERM, and uncaughtException so the terminal can't be left stuck in alt mode. Falls back to no-op when stdout isn't a TTY (piped output, CI). Trade-off: the TUI session vanishes on exit (post-exit context lives in `.liner-runs/` and `MIXTAPE.md`, which were always the source of truth anyway).
164
+ - 2026-05-22 — Process manifest: aggregator over `.liner-runs/*.jsonl` produces `process.json` (tokens / cost / tool calls / fetched URLs / domains / per-run breakdown). New CLI commands `liner manifest` + `liner status`. New TUI surface `ProcessManifest.tsx`, reachable via `[p]` on ProjectHub.
165
+ - 2026-05-22 — Compile auto-start from TapeDraftReview: accepting the source checklist now navigates directly to compile (CompileView already auto-starts on mount), removing the redundant "press enter to compile" second confirmation.
166
+ - 2026-05-22 — Compile re-run hint labeled per phase: "retry failed" when partial/failed (cache makes this true in effect), "re-run" when fully succeeded.
167
+ - 2026-05-22 — Web fetcher bot-challenge auto-fallback: `WebHandler` now raises `JsRenderingRequired` (not `HandlerHardFailure`) on 4xx/5xx responses whose body matches Cloudflare / Akamai / Imperva / PerimeterX signatures. Compile's existing auto-fallback path retries via `web_js` (Playwright). New helper `looks_like_bot_challenge()` in `html_extraction.py`.
168
+ - 2026-05-22 — Agent-summary fallback at compile: when all fetcher tiers fail, compile recovers the URL from `.liner-runs/` (the agent's WebFetch summary captured during research) and writes it as the source body with `metadata.extraction = "agent-summary"`. MIXTAPE.md surfaces a `Provenance: summary captured during research` line so the curator knows. Verified live on the Medium URL in cli-writer-6.
169
+ - 2026-05-22 — Orphan source-file cleanup: `write_mixtape()` now garbage-collects `sources/NN-*.md` files from prior compiles whose slug no longer matches the current title. Safe — only touches files matching the compile-output signature; curator-added files survive.
170
+ - 2026-05-22 — Framing-gap rubric rewrite: split coverage into `stance` vs. `concerns` to stop the methodology from treating "scriptability concerns covered by humans-first sources" as full coverage of a Unix-purist stance. Three actions now possible: (a) backfill, (b) argue concerns sufficient with explicit trade-off, (c) flag bias. Editied in both `quality-check-tests.md` and the Phase 5 prompt in `prompts.ts`.
171
+ - 2026-05-22 — Source-kind balance test (Test 5): every mixtape's `kind` distribution must be defended if any kind is zero. Catches the v6 case of 0 reference sources. Documented in `quality-check-tests.md`; Phase 5 prompt enforces.
172
+ - 2026-05-22 — Methodology mode hidden from the wizard surface: new mixtapes default to quick mode, the mode-selection step is gone, ProjectHub's `[m]` toggle is removed. Underlying methodology code (gates, prompts, mode field) is preserved for forward compatibility with existing methodology-mode mixtapes.
173
+ - 2026-05-22 — "Add your own source" affordance in TapeDraftReview: `[+]` opens an inline URL prompt; the URL gets appended to the working draft as a checked, curator-added source (auto-detected web/youtube type). Surfaces in the helper text + KeyHints so the affordance is discoverable.
174
+ - 2026-05-19 — Slice 1: 8-step wizard, ProjectHub two-pane phase tracker, scaffolding helpers.
175
+ - 2026-05-19 — Slice 2: Agent adapter (Claude + Codex), PhaseRunner screen, hub `r` key.
176
+ - 2026-05-19 — Polish pass: terminal-ui audit (5 CRITICAL/HIGH fixes), brand chip header, next-steps callout, background-color row selection, wizard step chip + progress dots, KeyHints wrap.
177
+ - 2026-05-19 — Slice 3 functional: auto-launch on `LINER_AGENT=` pinning, narrowed Claude tool whitelist (`--allowedTools Read Write Edit Glob Grep WebFetch`), Gate 1 review screen (parses `02-candidate-longlist.md` by section), Gate 2 review screen (parses `03-evaluation.yaml` as keep/trim/drop + `04-quality-checks.md` findings, tabbed view). Concurrent-run guard resolved by current cancel-on-unmount architecture.
178
+ - 2026-05-19 — Stream-JSON parsing: normalized `AgentEvent` type + per-CLI parsers (Claude `--output-format stream-json --verbose`, Codex `--json`), `LineBuffer` for partial-line chunking, 14 parser unit tests. PhaseRunner redesigned around structured events — top pane shows tool calls with status glyphs, middle pane streams assistant text in a bordered box, status bar shows event count + cost + duration from `summary` events.
179
+ - 2026-05-19 — Final-message preservation: PhaseRunner emits a notification on completion containing the first line of the agent's final response (or last text block for Codex), so the message survives navigation back to the hub.
180
+ - 2026-05-19 — Tool-call expand mode: `t` key toggles between tail (last 8) and full list.
181
+ - 2026-05-19 — Phase 7 agent-driven assembly: agent prompt now writes to `working/07-tape-draft.yaml` (never touches `tape.yaml` directly). New `TapeDraftReview` screen parses the draft, shows sections + source list + curator note for the cursor, with `a` accept (merges sources into tape.yaml + deletes draft), `e` edit (loads into source editor), `d` discard. PhaseRunner auto-routes to draft review on successful assembly run; hub shows "draft pending" hint and routes `enter` on Phase 7 to the review when a draft is on disk.
182
+ - 2026-05-19 — Hub key model rewrite per CLI-research synthesis (Skip-or-Enter §2.8, Caligula condense-one-prompt, "don't hide features behind keys"): **Enter is now the single primary action per phase** — runs the agent for agent-eligible phases (or falls back to $EDITOR with notification if no agent installed); opens gate review for gates; routes to draft review on Phase 7 when a draft exists; runs compile on the compile row. `e` is the explicit manual escape hatch ($EDITOR). Removed `E`/`c`/`R` as separate top-level keys. `r` kept as a hidden alias for Enter (back-compat). Right-pane action labels read aloud naturally ("run Phase 1 with the agent", "review the candidate long-list", etc.).
183
+ - 2026-05-19 — Hot fixes: (a) `require is not defined` crash in `phases.ts` writeGateState — replaced CJS require with imported writeFileSync; (b) PhaseRunner scrollback-laddering on long agent runs caused by dynamic content overflowing terminal — compacted running view to spinner + one-line stats + latest tool only (no streamed text, no full tool list); (c) live cumulative token counter via new `tokens` event extracted from Claude `assistant.usage` / Codex `turn.completed.usage`; (d) done state now leads with a NextSteps panel and Enter advances to the next logical screen (Phase 2 → Gate 1, Phase 4 → Phase 5, Phase 5 → Gate 2, etc.); (e) Gate 1 and Gate 2 reframed — Enter = accept + auto-advance, summary leads the screen, scroll list visually demoted; (f) auto-launch when only one agent is installed (was: still showed picker).
184
+ - 2026-05-19 — Wizard placeholder pattern: stopped pre-filling draft state (curator no longer pre-populated with $USER; title/description no longer pre-populated from JTBD). Suggestions surface via TextInput placeholder; Enter on empty submit accepts the suggestion. Going back to a previously-answered step from review still shows the existing value for editing. Removes the "I have to delete the previous question's text" friction.
185
+ - 2026-05-19 — Path-aware truncation in PhaseRunner: `truncatePath` keeps the basename (e.g. `…/working/02-candidate-longlist.md`) instead of right-trimming the prefix. Tool-call previews route through `previewify()` which detects paths vs. URLs vs. plain strings.
186
+ - 2026-05-19 — PhaseRunner running view shows phase label inline ("Phase 2 — Candidate discovery · Claude Code") so users always know where they are without looking up at the header.
187
+ - 2026-05-19 — Removed `r` re-run from the done state — user feedback was it had no value (re-running an agent with the same prompt is unlikely to give a different result). Done state actions: Enter advances, b/esc backs to hub.
188
+ - 2026-05-19 — Hub focus mode: default view is now a single hero card for the current incomplete phase + a one-line progress strip showing all phases with status glyphs. `l` toggles into the full TOC list (existing two-pane view) with future-phase locking. Esc from TOC returns to focus; esc from focus backs to browser.
189
+ - 2026-05-19 — Quick mode now skips gate review screens (per CURATION.md v2.0 "Quick mode defaults gates to continue"). PhaseRunner.nextScreenFor reads `tape.mode`; quick mode auto-writes `gate1Accepted` / `gate2Accepted` to `.liner-gates.json` and routes directly from candidates → evaluation and from quality → synthesis. Methodology mode still shows the gates.
190
+ - 2026-05-19 — Gate review screens slimmed down (methodology mode): removed the scrollable candidate / evaluation list. Now a bordered summary card (counts + section breakdown) plus a NextSteps panel. Inspection is delegated to `$EDITOR` via `e` — the rendered list was never going to compete with a real editor for actual reading.
191
+ - 2026-05-19 — Editor default switched from `vi` → `nano`. New `src/editor.ts` resolves `$VISUAL` → `$EDITOR` → probes for `nano`/`pico`/`vi` on PATH. Vi is hostile if you don't already know it; nano shows its keybindings at the bottom of the screen and is on every macOS install. All four screens (ProjectHub, Gate1Review, Gate2Review, TapeEditor) route through the helper.
192
+ - 2026-05-19 — Agent resume on failure: PhaseRunner's failed-done state now offers "Press Enter to resume" (cheap continuation via `claude --continue` / `codex exec resume --last`). The previous session's conversation — prompt, tool-call results, partial work — stays in context, so the agent doesn't re-fetch anything. `r` falls back to re-run from scratch. Runner accepts `resume: true`; on resume it sends a tiny "continue from where you left off" nudge instead of re-shipping SKILL.md. Failure-state NextSteps and KeyHints now lead with "resume" instead of the misleading "continue".
193
+ - 2026-05-19 — Done state collapsed to two visible choices: `enter` (continue on success / try again on failure) + `b` (back to hub). `r` (re-run from scratch) and `t` (expand tools) remain bound as hidden power-user escapes but no longer clutter the NextSteps panel or KeyHints. Failure-state copy reworded to "try again — picks up where the agent stopped, no re-fetching" so the user isn't decoding "resume" terminology.
194
+ - 2026-05-19 — Phase list cleanup: (a) **dropped Phase 3 (Fetching)** — it was a methodology step that does nothing in Liner (the agent fetches automatically at compile time), so a row that said "✓ complete · happens at compile" was actively misleading. Removed from PhaseId, computePhases, ProjectHub.enterPhase, primaryActionLabel. (b) **Tightened future-phase lockout in TOC mode**: anything past the current incomplete phase is now blocked from entry, not just `not_started` ones — prevents out-of-order runs. (c) **Sequential status enforcement**: once a phase is non-complete, any later "complete" downgrades to ⚠ needs_review with `· earlier phases not complete` appended to the detail. Stops the swiss-cheese hub view where Phase 7 shows ✓ but Phase 2 is empty. Phase 8 (empirical, optional) is exempt from the sequential rule.
195
+ - 2026-05-19 — **Progress cursor model** (replaces per-artifact status entirely). New `src/progress.ts` owns `.liner-progress.json` (one int: `step`). Phase status is now derived purely from the cursor (`i < step → ✓`, `i === step → ▶`, `i > step → ○`), not from filesystem checks. Detail strings still pull from disk for context but don't drive the badge. `markPhaseComplete()` advances the cursor only when called for the current phase (idempotent, refuses out-of-order advance). One-time migration on hub mount walks `PHASE_ORDER` and sets step to the longest consecutive "done" prefix — handles existing projects from older builds. Wired into all advancement points: PhaseRunner done-success (except assembly), Gate1/Gate2 accept, TapeDraftReview accept (advances "assembly"), CompileView result with failed=0, quick-mode gate auto-skip in `nextScreenFor`. The legacy `enforceSequentialOrder` patch is gone — no longer needed. 12 new unit tests for progress.ts.
196
+ - 2026-05-19 — **Tee-style audit log** (`src/agents/run-log.ts`). Every agent run writes raw JSONL to `<project>/.liner-runs/<phaseId>/<isoTs>.jsonl` with a `_liner_meta` header, raw stream events, stderr lines (wrapped to avoid masquerading as JSON), and a `_liner_close` marker. Not load-bearing for resume (Claude's session.json already handles that) — gives us a per-run transcript curators can scroll back through and a forensic record when things misbehave.
@@ -0,0 +1,84 @@
1
+ # Curator notes
2
+
3
+ Loaded by the `curating-mixtapes` skill at the start of Phase 4 (Evaluation).
4
+
5
+ This file describes how to draft curator notes. Apply it whenever you're writing the `note` field for a kept or trim source. Notes are drafted in Phase 4 during evaluation and land in `tape.yaml` at Phase 7 — write them in their final form now; don't postpone the work.
6
+
7
+ Curator notes are the highest-leverage feature in the mixtape format. The note is what tells the consuming AI which sources matter for which questions. The synthesis frames the domain; the notes route the AI's attention to specific sources when a specific question arises. Without notes, the AI sees a list of sources and has to guess which ones are relevant. With good notes, the AI can route precisely.
8
+
9
+ This is what "liner notes" means in the product name. The note is doing real work.
10
+
11
+ ---
12
+
13
+ ## The three-thing template
14
+
15
+ Every good note answers three questions about its source:
16
+
17
+ 1. **Why is this source in the mixtape?** What role does it play? Is it foundational, supplementary, contested, illustrative? "Watch first — this is the foundational piece." "Skim if time permits — useful for context but not essential." "The contested counterpoint to Source 4."
18
+
19
+ 2. **Where is the high-value portion?** Most sources are not uniformly dense. A talk's first ten minutes might be setup; a paper's middle section might be the methodology no one needs; an article's three closing paragraphs might be the only part that matters. Name it. "The first ten minutes are setup; the load-bearing content starts around 10:30." "Section 3 is the substantive one." "Skip the introduction; the framework is in the second half."
20
+
21
+ 3. **What are the source's limitations?** Where is this source out of date, narrow, or biased? "Dated on platform specifics, durable on principles." "Strong perspective; read alongside Source 7 for the counterargument." "Pre-2022 — doesn't address [recent development]."
22
+
23
+ A note that addresses all three is doing its full job. A note that addresses one or two is adequate. A note that addresses none — "this is a useful resource" — is useless and shouldn't ship.
24
+
25
+ ---
26
+
27
+ ## Length
28
+
29
+ **15–40 words typically.** Shorter is fine when the source is self-explanatory. Longer is usually a sign of one of two things:
30
+
31
+ - The source needs more framing than a note should carry. Move some of the framing into the synthesis instead.
32
+ - The note is doing work the synthesis should be doing. If you're explaining a framework concept in a note, that's a synthesis problem — the note is patching for the synthesis's gap.
33
+
34
+ When a note exceeds 60 words, stop and ask which of these two patterns is happening. Fix the underlying issue rather than padding the note.
35
+
36
+ ---
37
+
38
+ ## What makes notes bad
39
+
40
+ Notes drift toward generic praise by default. These are the patterns to watch for in your own drafts.
41
+
42
+ - **"This is a useful resource."** Says nothing. Names no role, no location of value, no limitation. The AI can't route on this. Replace it with a specific answer to at least one of the three questions.
43
+ - **"Comprehensive overview of [topic]."** Implies the source is uniformly valuable, which is almost never true. Even if the source really is comprehensive, the AI needs to know which parts matter for which questions.
44
+ - **"Highly recommended."** Reviewer-style praise, not curator routing. The fact that a source was kept means it's recommended. The note's job is to say *how to use it*, not to vouch for it.
45
+ - **Restating the title or abstract.** If the title is "Designing CLIs People Love," the note shouldn't say "About designing CLIs people love." Say what *role* it plays in this corpus.
46
+ - **Pure summary.** "Argues that CLIs should follow Unix conventions." That's what the source says. The note should say what the source is *for* in this mixtape — foundational, contested, etc.
47
+
48
+ ---
49
+
50
+ ## How notes interact with the synthesis
51
+
52
+ The synthesis and the notes do different jobs.
53
+
54
+ - **The synthesis** frames the whole domain. It's what the consuming AI reads first, and it sets up the curator's view of the territory.
55
+ - **The notes** route the AI's attention to specific sources during a specific conversation. When a question comes up that one source addresses particularly well, the note is the signal that says "open this one."
56
+
57
+ This division is why notes don't need to explain the source's content — the synthesis already provided the conceptual frame. The note's job is positional, not explanatory.
58
+
59
+ A common failure mode is writing notes that try to teach the AI what the source says. That's the synthesis's job. The note's job is to tell the AI when and how to use the source.
60
+
61
+ ---
62
+
63
+ ## Quick mode vs. methodology mode
64
+
65
+ **Quick mode:** AI drafts the note during Phase 4. Use the three-thing template. Show the curator the drafted notes at Gate 2. Default is "looks good, save it." Light edits welcome.
66
+
67
+ **Methodology mode:** AI drafts a starting point. Expect the curator to rewrite each note substantively. The notes carry the curator's voice and the curator's specific framing of what each source is for. AI-drafted notes with light edits don't meet the methodology-mode bar.
68
+
69
+ In both modes, notes are required. A source without a note doesn't ship.
70
+
71
+ ---
72
+
73
+ ## Worked examples
74
+
75
+ > TODO: Insert three to five worked examples from the Cowork CLI/TUI synthesis. Each should show all three things landed. Look for notes in the Cowork material that are concrete about role, location of value, and limitations — not vague praise.
76
+ >
77
+ > Suggested examples to pull:
78
+ > - A "watch first" foundational note (likely on a Van Slyck talk or clig.dev)
79
+ > - A note with specific time-coding on a video ("the section starting at 14:30")
80
+ > - A trim note that explicitly says what to skip ("Skip the OpenStack-specific noise")
81
+ > - A "contested counterpoint" note that names the source it disagrees with
82
+ > - A note that names a temporal limitation ("dated on X, durable on Y")
83
+
84
+ > TODO: Insert one or two examples of bad notes for contrast. Pull the original AI-drafted notes from OpenClaw if they're available — those are the canonical "this is a useful resource" generic notes that Cowork rewrote.
@@ -0,0 +1,196 @@
1
+ # Quality-check tests
2
+
3
+ Loaded by the `curating-mixtapes` skill at the start of Phase 5 (Quality checks).
4
+
5
+ This file describes the four tests every mixtape should pass before moving to synthesis. Apply them deliberately, in this order. Write findings to `working/04-quality-checks.md`.
6
+
7
+ Phase 5 is the methodology's correction for single-pass curation. The first four phases work forward — frame, find, fetch, evaluate. Phase 5 works backward — looking at the whole keep-pile and asking what's wrong with it. The two passes do different work. If you skip this phase, the mixtape's blind spots ship with the mixtape.
8
+
9
+ The framing-gap test is the highest-leverage of the four and the one most curators skip.
10
+
11
+ ---
12
+
13
+ ## Setting up the phase
14
+
15
+ Before running the tests, gather the inputs in one place:
16
+
17
+ - The JTBD (from `working/01-jtbd-and-knowledge-map.md`)
18
+ - The knowledge map (same file)
19
+ - The kept and trim sources from `working/03-evaluation.yaml` — titles, sections, ratings, rationales, and the drafted curator notes
20
+
21
+ Read these together. The tests are about how the corpus *as a whole* serves the JTBD. You can't run them well by looking at sources one at a time.
22
+
23
+ ---
24
+
25
+ ## Test 1 — The redundancy test
26
+
27
+ Read each kept source's role in the mixtape. Are any two sources making essentially the same point?
28
+
29
+ If yes, keep the better one and cut the other. Volume is not a virtue. Five excellent sources beat fifteen good ones.
30
+
31
+ **The test in action:** for each kept source, write down in one sentence what unique contribution it makes to the corpus. If two sources produce the same sentence (or near-same), one of them is redundant. Drop the weaker.
32
+
33
+ Redundancy is different from coverage. Two sources covering the same topic from different angles or with different evidence is coverage, not redundancy. The test is whether the AI would generate meaningfully different output with both vs. with only one. If not, redundant.
34
+
35
+ > TODO: Insert a worked example from the Cowork synthesis where two sources were collapsed because of redundancy. The Van Slyck talk appearing in transcripts 02 and 03 is a known case — same talk uploaded twice. Show how the redundancy was named and resolved.
36
+
37
+ ---
38
+
39
+ ## Test 2 — The coverage test
40
+
41
+ Walk through the knowledge map. For each section, ask: does this section have at least one strong source?
42
+
43
+ If a section has zero sources, two responses are valid:
44
+
45
+ - **Fill it.** Return to Phase 2 for that section. Find candidates. Fetch them. Evaluate them. Then come back to Phase 5.
46
+ - **Explicitly note the gap.** Some sections of a domain genuinely don't have credible sources available, or fall outside what this mixtape is trying to do. Document this in `working/04-quality-checks.md`: "This mixtape doesn't cover X — see [other mixtape] for that, or note that the field doesn't have a canonical reference here."
47
+
48
+ A mixtape that silently omits a major area is worse than one that says explicitly "this mixtape doesn't cover X." The latter sets expectations correctly; the former misleads the consuming AI by implying the corpus is complete.
49
+
50
+ If a section has sources but they're all rated 2 or 3, that's a weak-coverage signal — the section is technically populated but the sources aren't load-bearing. Either find stronger sources or note the weakness.
51
+
52
+ > TODO: Insert a worked example. If the Cowork synthesis had a section that needed reinforcement after first-pass evaluation, show the coverage check that surfaced it and how the gap was addressed.
53
+
54
+ ---
55
+
56
+ ## Test 3 — The disagreement test
57
+
58
+ Find the strongest claim made by sources in the mixtape. Is there someone credible who disagrees?
59
+
60
+ If yes, either include the disagreement or explicitly note that the mixtape takes a position.
61
+
62
+ A corpus where every source agrees teaches the AI no nuance. The AI then can't see the contested-ness of contested questions, which means it can't represent them honestly downstream. The fix is to include at least one strong dissenting source on the most-contested point in the corpus.
63
+
64
+ If the topic is genuinely uncontested — the W3C HTML spec, for example, isn't really contested in the way a design philosophy might be — that's fine, and the working notes should say so. The test isn't "manufacture disagreement"; it's "if disagreement exists, surface it; if it doesn't, document why."
65
+
66
+ **The test in action:** identify the strongest claim in the corpus. Search for "[claim] critique" or "[claim] is wrong" or "alternative to [claim]." If you find a credible critique you haven't included, you've found your dissenting source. Add it.
67
+
68
+ > TODO: Insert a worked example from CLI/TUI research. The corpus probably had a contested-question moment — possibly around whether CLIs should follow Unix conventions strictly vs. break them deliberately, or around accessibility being assumed-by-default vs. explicitly designed-for. Surface the actual disagreement and how it was handled.
69
+
70
+ ---
71
+
72
+ ## Test 4 — The framing-gap test
73
+
74
+ Step back from individual sources. Is there a major perspective on this topic missing entirely — not just an individual source, but a whole way of thinking about the JTBD?
75
+
76
+ If yes, the framing was too narrow. Expand the knowledge map and return to Phase 2.
77
+
78
+ **This test is the highest-leverage of the four and the one most curators skip.** Single-pass curation tends to produce mixtapes that are well-covered within one narrow framing. The framing-gap test catches what the first four phases couldn't see.
79
+
80
+ ### How to run it (required steps, in order)
81
+
82
+ This test cannot be answered yes/no. Earlier versions of this methodology allowed a casual judgment ("does the framing feel wide enough?") and the answer was almost always "yes" — because the test, run that way, has no force. Run it as follows instead:
83
+
84
+ 1. **Name 2–3 candidate perspectives that could exist *outside* the corpus.** Write them down in `working/04-quality-checks.md` before looking at the keep-list. Common candidates: designer voice, accessibility-first viewpoint, security/abuse perspective, non-English-speaking practitioner, contrarian who disagrees with the dominant framing, an adjacent discipline that owns part of the problem space (e.g. for a CLI mixtape: visual-design tradition, technical-writing tradition, OS-vendor convention tradition).
85
+
86
+ The named perspectives should be specific enough to act on. "User perspective" is too vague. "iOS Human Interface Guidelines designer perspective on form-field labels" is actionable.
87
+
88
+ 2. **For each named perspective, classify coverage in two dimensions, not one.** The earlier single-axis judgment ("covered / uncovered / partial") let a corpus mark a perspective `covered` just because some kept source addressed its concerns — even when no source actually argued *for* the perspective as a stance. That collapse is the failure mode this split exists to prevent.
89
+
90
+ - **Stance** — is there a verified, fetchable source whose author explicitly *argues for* this perspective as a design center of gravity? Mark `stance-represented` or `stance-absent`.
91
+ - **Concerns** — do any kept sources address the perspective's operational concerns mechanically, even while arguing from a different stance? Mark `concerns-addressed` or `concerns-absent`.
92
+
93
+ A perspective is fully `covered` only when its stance is represented. `concerns-addressed` alone is a **soft gap** — the corpus internalizes the concern without giving the consuming AI a worked rival argument to cite. Soft gaps are real gaps; they show up later as synthesis bias.
94
+
95
+ 3. **Unverified sources DO NOT count as coverage.** A source whose Phase 4 curator note acknowledges unfetched content, broken URLs, paywalled access, or transcripts that couldn't be obtained cannot satisfy a perspective slot. "We have one designer voice, but her transcript wasn't fetchable" is the same as "we have no designer voice." Tokenism passes the test cheaply and silently — don't allow it.
96
+
97
+ 4. **For each perspective that is not `stance-represented`, take exactly one of three actions:**
98
+
99
+ a. **Search for a stance source.** Return to Phase 2 with vocabulary derived from the perspective itself: *who would argue for this position, what would they write, where would they publish?* This is different from a topic search — you're looking for an opinionated author, not a neutral reference. Examples: "Brandur Leach on terminal density," "Rob Pike on Unix philosophy," "Don Norman on visceral design," not "CLI scriptability best practices." Spend one search pass. If you find a verified source that fits, add it to the keep-list.
100
+
101
+ b. **Argue that the concerns are sufficient.** If concerns are addressed and you believe the perspective doesn't need a separate stance source — because the operational disagreement is genuinely thin — *write the argument explicitly*: "Concerns covered by [Sources N, M] inside the [dominant] stance. The dissenting stance is real but its operational implications are absorbed; no separate source needed."
102
+
103
+ This is not a free pass. The methodology requires you to *state* the trade-off. If you can't articulate why concerns are sufficient without a stance source, you don't actually have the argument and should fall back to (a) or (c).
104
+
105
+ c. **Flag the bias explicitly.** If no source is found and the concerns aren't sufficient, write in `working/04-quality-checks.md`:
106
+
107
+ > *Perspective: [name] — stance unrepresented after one search pass. Corpus argues from [dominant stance] but no source argues for [rival stance]. Recommendation: ship as-is and document the bias in the synthesis, OR weaken the JTBD claim that requires the rival stance.*
108
+
109
+ Do NOT silently leave a perspective `stance-absent` with no defense. The synthesis is what the consuming AI reads first; an undocumented bias becomes the AI's silent default.
110
+
111
+ ### The output format
112
+
113
+ `working/04-quality-checks.md` must include a top-level section like this:
114
+
115
+ ```
116
+ ## Perspectives audit
117
+
118
+ - Designer voice — stance-represented (Source 14: Gillet, "Designing for CLI", verified) ✓
119
+ - Accessibility-first viewpoint — stance-absent, concerns-absent. Search added GitHub accessibility post → now stance-represented (Source 3) ✓
120
+ - Power-user / Unix-purist stance — stance-absent, concerns-addressed by Heroku/Vercel/Van Slyck.
121
+ - Backfill attempt: searched "Brandur Leach terminals density," found brandur.org/interfaces. Verified, added (Source N). ✓
122
+ OR
123
+ - Argued sufficient: concerns covered by Heroku's grep-first rule + Vercel's stdout contract + Van Slyck's "friendly to humans AND scripts" pillar. The Unix-purist stake is that terseness should be the *center of gravity*, not a preserved capability — we're not adopting that. The corpus's framing covers the operational concerns without representing the stance; synthesis will name this trade-off explicitly.
124
+ ```
125
+
126
+ This format is checked by the TUI: a quality-checks file without a "Perspectives audit" section signals that the test wasn't run honestly.
127
+
128
+ ### Why this strictness
129
+
130
+ The earlier loose version of this test failed quietly in practice. A real session keeping one designer source whose content was never fetched produced a corpus the curator described as "engineering-heavy, one designer voice unverified" — and the quality-check still passed because "1 source ≥ 1 = covered." Naming perspectives in advance and refusing to count unverified sources is what makes the test do work instead of legitimize tokenism.
131
+
132
+ If the framing gap is real, accept the cost of going back. Phase 2 is cheap relative to shipping a mixtape with a hole in it.
133
+
134
+ > TODO: Insert the canonical worked example from the Cowork synthesis. OpenClaw's initial 50-source list was anchored in "CLI/TUI implementation" framing and missed "the entire wizard/form-design tradition (Form Design Patterns, NN/g articles, Tidwell, Cooper)." Cowork ran the framing-gap test, named the missing tradition, added 43 net-new sources, and reframed the corpus. This is the textbook framing-gap-test rescue. Pull the specific moment the gap was identified and the specific sources added.
135
+
136
+ ---
137
+
138
+ ## Test 5 — Source-kind balance
139
+
140
+ Look at the distribution of `kind` values across the keep-list. Every source in `tape.yaml` should carry one of: `reference / principle / prescription / example`.
141
+
142
+ The four kinds represent four argumentative roles. A corpus missing one of them has a structural gap, even when every knowledge-map section is technically populated:
143
+
144
+ - **0 `reference` sources** → the consuming AI has no substrate to cite when defending a convention. The mixtape becomes opinion against opinion when challenged. The fix is at least one authoritative source — a spec, an official manual, a widely-adopted standard, an RFC — that the AI can point at as "this is canon, not just our preference."
145
+ - **0 `principle` sources** → the synthesis has no philosophical anchor. The mixtape can describe rules but can't justify the worldview behind them. The fix is a stance-setting essay or manifesto.
146
+ - **0 `prescription` sources** → the AI has no concrete rules to enforce. The synthesis becomes vibes without operational consequences. The fix is a style guide, rule-set, or explicit guideline doc.
147
+ - **0 `example` sources** → the AI has no taste calibration. It can recite rules but can't recognize good when it sees it. The fix is a worked instance, case study, or annotated specimen.
148
+
149
+ Imbalance is not a failure. A 7-principle / 2-prescription / 1-reference / 0-example corpus may be exactly right for a philosophy-heavy JTBD. But a zero in any column should be a **decision, not an accident.** If you accept a zero, write the defense in `working/04-quality-checks.md`:
150
+
151
+ > *Kinds audit: 7 principle / 9 prescription / 5 example / 0 reference. Accepted: this JTBD is about voice and microcopy, not architectural conventions. No reference source is needed because the synthesis doesn't make authority claims that would require backing.*
152
+
153
+ If the zero isn't defensible, run one search pass for a source of the missing kind before shipping. The same rule as Test 4(a) applies: search for the role the kind plays (an authoritative spec, an opinionated essay, a tight rule-set, a worked example), not for the topic generically.
154
+
155
+ ### Required output
156
+
157
+ `working/04-quality-checks.md` must include a Test 5 section like this:
158
+
159
+ ```
160
+ ## Test 5 — Source-kind balance
161
+
162
+ Distribution: X reference / Y principle / Z prescription / W example
163
+
164
+ [If any kind is zero: either a backfill action OR a defense paragraph in the form above.]
165
+ ```
166
+
167
+ ---
168
+
169
+ ## What to do when a test fails
170
+
171
+ Don't paper over failures. The point of running the tests is to find problems while they're still cheap to fix.
172
+
173
+ - **Redundancy fails:** drop the weaker source, update `working/03-evaluation.yaml` to reflect the change, document the decision in `working/04-quality-checks.md`.
174
+ - **Coverage fails:** return to Phase 2 for the missing section. Fetch new candidates. Evaluate them. Come back to Phase 5 and re-run all four tests on the new keep-list.
175
+ - **Disagreement fails:** find one strong dissenting source. Fetch it. Evaluate it. Add it to the keep-list with a note that names its role as counterpoint.
176
+ - **Framing-gap fails:** this is the expensive one. Expand the knowledge map. Return to Phase 2. Find candidates for the new sections. Fetch, evaluate. Come back to Phase 5 with a substantially revised keep-list and re-run all four tests.
177
+
178
+ Each backtrack is a sign the methodology is working, not failing. The first four phases produced a corpus that worked from one angle; Phase 5 found the angle that wasn't covered. Better to find it here than in the empirical test (Phase 8) or — worse — silently, when the mixtape is in use.
179
+
180
+ ---
181
+
182
+ ## Output: `working/04-quality-checks.md`
183
+
184
+ Document each test, the finding, and the action taken. Even tests that passed without changes should be noted — "redundancy test: no redundant sources found." The working notes are part of the methodology; they show what work was actually done.
185
+
186
+ > TODO: Insert a sample `working/04-quality-checks.md` from the Cowork synthesis. The full structure with each test, the finding, and the resulting action is the most useful worked example in this file.
187
+
188
+ ---
189
+
190
+ ## A note on fresh attention
191
+
192
+ Phase 5 benefits from running with fresh attention. The first four phases build up a mental model of the corpus that biases how you see it — you remember why you kept each source, which makes redundancy easier to miss; you remember the candidate searches you ran, which makes the framing-gap easier to miss.
193
+
194
+ If the conversation has been long, consider starting a separate chat with just the JTBD, the knowledge map, and the kept-source list (titles + notes only, no source content). Run the four tests there. The fresh chat doesn't carry the gathering pass's biases.
195
+
196
+ This is optional, not required by the methodology. Mention the option to the curator. Quick mode users may prefer to continue in the same conversation for speed; methodology mode users often benefit from the reset.
@@ -0,0 +1,99 @@
1
+ # Source-finding tactics
2
+
3
+ Loaded by the `curating-mixtapes` skill at the start of Phase 2 (Candidate discovery).
4
+
5
+ This file describes the six tactics that produce better candidates than generic search. When you reach Phase 2, work through these tactics — not all of them for every mixtape, but enough that the candidate pool covers the knowledge map from multiple angles.
6
+
7
+ The goal of Phase 2 is recall, not precision. You're producing two to four times the eventual kept count. You will cut in Phase 4. Casting wide here is the methodology working as designed.
8
+
9
+ ---
10
+
11
+ ## 1. Follow the citations
12
+
13
+ Pick one excellent source you already have. Find what *it* cites — the references, the linked sources, the "see also" pointers. Then open one of those and find what *it* cites. Three or four hops in, you'll find the canonical sources nobody links to anymore because everyone assumes you've read them.
14
+
15
+ This tactic is the single highest-leverage move for discovering primary documents. It works against your popularity bias: cited-by-the-canon sources don't surface in keyword search, but they're what serious work in the field rests on.
16
+
17
+ **How to apply:** Open the most credible source you have. Scan the references, footnotes, or "further reading" section. Note every source that's cited *and* recurs in another credible source's references. Recurrence across multiple credible sources is the signal — it's how you find the references nobody links anymore.
18
+
19
+ > TODO: Insert worked example from the Cowork CLI/TUI synthesis. Look for a moment in the research where citation-chasing surfaced a canonical source that didn't show up in any initial keyword search. Form Design Patterns by Adam Silver is a candidate — it's cited across multiple Phase 1 sources but didn't surface from "CLI wizard design" searches.
20
+
21
+ ---
22
+
23
+ ## 2. Reverse-engineer experts' reading lists
24
+
25
+ Many domain experts publish their own reading lists or syllabi. These already encode someone else's curation work. Use them.
26
+
27
+ **Where to look:** Notion (search "site:notion.so reading list <topic>"), GitHub (`awesome-<topic>` repositories, individual `README.md` files in personal repos), Are.na (channels — Are.na in particular is underused for this), personal blogs, course-instructor pages.
28
+
29
+ Are.na deserves a specific note: it's a network designed for visual and textual reference-collecting. Practitioners use it to curate the kind of sources that don't make it into mainstream publications. Constrain a search with "site:are.na <topic>" and look for channels related to your JTBD.
30
+
31
+ **How to apply:** Find three to five experts in the domain. Search each one's name plus "reading list" or "syllabus" or "references." Catalog what they recommend. Cross-reference with the candidates already on your long-list — overlaps are strong signal; uniques are leads.
32
+
33
+ > TODO: Insert worked example from the Cowork CLI/TUI synthesis. Look for a tactical mention of an expert reading list that surfaced relevant work. If none exists, this section can use an example from a different domain — the methodology generalizes.
34
+
35
+ ---
36
+
37
+ ## 3. Mine course syllabi
38
+
39
+ University courses, bootcamp curricula, and serious online courses have already done curation work for their domain. A well-designed syllabus is a curated reading list optimized for learning. Use them.
40
+
41
+ **Productive queries:**
42
+
43
+ - `"<topic> syllabus" filetype:pdf`
44
+ - `"course readings" <topic>`
45
+ - `<topic> "required reading"`
46
+ - University course catalogs for the relevant department
47
+
48
+ **How to apply:** Find two to three syllabi on your topic. Note the readings that appear across multiple syllabi — those are the canonical pieces. Note the readings that appear once but are written by people you recognize — those are the practitioner-credible additions.
49
+
50
+ Course syllabi skew toward foundations. They're best for the early-section knowledge-map buckets. Recent practitioner work is rarely on them.
51
+
52
+ > TODO: Insert worked example. If no syllabus surfaced in the CLI/TUI research, note this and use a hypothetical that's specific enough to be useful.
53
+
54
+ ---
55
+
56
+ ## 4. Find who experts cite
57
+
58
+ Pick three to five acknowledged practitioners in your domain. Look at *their* references — bibliographies, acknowledgments, who they cite in their own writing. The overlap across these experts is your shortlist.
59
+
60
+ This tactic is structurally similar to citation-chasing (#1), but starts from people rather than from sources. Use it when you have a clear sense of who the credible practitioners are but no clear sense of which of their works is canonical.
61
+
62
+ **How to apply:** Identify three to five practitioners credible in the domain. Open their most recent significant work. Note the sources they cite. Open the sources cited by two or more practitioners. Those are your high-priority candidates.
63
+
64
+ > TODO: Insert worked example from CLI/TUI research. Carolyn Van Slyck, Aanand Prasad (clig.dev), Will McGugan (Textualize), and Amanda Pinsker (GitHub CLI) are candidates whose citation patterns could be traced.
65
+
66
+ ---
67
+
68
+ ## 5. Conference proceedings
69
+
70
+ Going through three years of a specific conference is more efficient than topic-by-topic search. The conference's curation has already filtered for credibility and substance.
71
+
72
+ **How to apply:** Identify one or two conferences serious in the domain. Open their proceedings, talk lists, or YouTube channels for the last three years. Skim titles and abstracts. Flag any talk whose abstract addresses a knowledge-map section.
73
+
74
+ Conference talks vary widely in density. The same talk reposted across multiple conferences is one signal of substance. Talks from speakers who are also cited by other practitioners (tactic #4) are another.
75
+
76
+ > TODO: Insert worked example. The CLI/TUI corpus has multiple Van Slyck talks across GopherCon and other venues — a real example of how conference-proceeding mining surfaced both her work and what to keep when the same talk appears at multiple conferences.
77
+
78
+ ---
79
+
80
+ ## 6. Ask the AI to find gaps, not sources
81
+
82
+ Once you have a candidate list, stop searching and ask: *what's missing from this collection for someone trying to [JTBD]?*
83
+
84
+ AI is bad at recall — at remembering and surfacing sources you don't know about. AI is good at critique — at looking at a list and noticing structural gaps. Use it for the right thing.
85
+
86
+ **How to apply:** Show the candidate list (titles and one-line rationales) along with the JTBD and knowledge map. Ask explicitly: "What perspective is missing? What discipline is underrepresented? What kind of source is this list short on?" Then go find sources to fill the gaps named.
87
+
88
+ This tactic is structurally related to the framing-gap test in Phase 5, but earlier and lower-stakes. Doing it in Phase 2 is cheaper than discovering the gap in Phase 5 and having to backtrack.
89
+
90
+ > TODO: Insert worked example from the Cowork synthesis. The Cowork run discovered that OpenClaw's initial 50-source list missed "the entire wizard/form-design tradition (Form Design Patterns, NN/g articles, Tidwell, Cooper)" — this is the canonical example of gap-finding working. Pull the specific moment where the gap was named and how it changed the candidate pool.
91
+
92
+ ---
93
+
94
+ ## What not to do
95
+
96
+ - **Don't rely on generic search alone.** The first page of search results is what your audience could also find. The point of curation is to surface what they couldn't.
97
+ - **Don't accept candidates without verifying URLs.** AI hallucinates plausible-looking URLs. Web-fetch every URL before it goes on the long-list. A 404 candidate is worse than a missing one.
98
+ - **Don't filter at Phase 2.** That's Phase 4's job. If a source might be useful, it goes on the long-list. Quality decisions come after fetching and reading.
99
+ - **Don't over-research one section while leaving others empty.** Walk the knowledge map. Each section should have a reasonable candidate pool before you go deep on any one section.