@gi4nks/ph 1.4.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +147 -58
  3. package/dist/cli.js +2292 -1021
  4. package/dist/cli.js.map +1 -1
  5. package/docs/evals/context-retrieval-golden.json +26 -0
  6. package/docs/evals/context-retrieval.md +27 -0
  7. package/docs/hooks.md +13 -7
  8. package/docs/ph-analysis.html +145 -0
  9. package/docs/ph-manual.md +352 -231
  10. package/docs/specs/SPEC-001-architecture-cli.md +82 -0
  11. package/docs/specs/SPEC-002-database-layer.md +105 -0
  12. package/docs/specs/SPEC-003-capture-modes.md +110 -0
  13. package/docs/specs/SPEC-004-filter-metadata.md +82 -0
  14. package/docs/specs/SPEC-005-search.md +102 -0
  15. package/docs/specs/SPEC-006-analysis-pipeline.md +98 -0
  16. package/docs/specs/SPEC-007-memory-summaries.md +96 -0
  17. package/docs/specs/SPEC-008-embeddings.md +90 -0
  18. package/docs/specs/SPEC-009-retention-archive.md +91 -0
  19. package/docs/specs/SPEC-010-remote-sync.md +106 -0
  20. package/docs/specs/SPEC-011-mcp-server.md +94 -0
  21. package/docs/specs/SPEC-012-tui-browser.md +98 -0
  22. package/docs/specs/SPEC-013-importers.md +109 -0
  23. package/docs/specs/SPEC-014-analytics-commands.md +109 -0
  24. package/docs/specs/SPEC-015-config-env.md +85 -0
  25. package/docs/specs/SPEC-INDEX.md +35 -0
  26. package/docs/specs/SPEC-ISSUES.md +122 -0
  27. package/docs/specs/_TEMPLATE.md +65 -0
  28. package/docs/superpowers/plans/2026-06-12-ph-evolution-phase1.md +466 -0
  29. package/docs/superpowers/plans/2026-06-12-ph-evolution-phase2.md +351 -0
  30. package/docs/superpowers/specs/2026-06-12-ph-evolution-design.md +173 -0
  31. package/hooks/codex/README.md +54 -0
  32. package/hooks/codex/ph-hook.sh +14 -0
  33. package/hooks/opencode/ph-plugin.ts +60 -57
  34. package/package.json +13 -12
@@ -0,0 +1,26 @@
1
+ {
2
+ "version": 1,
3
+ "judging": "Maintainer-curated relevance labels; a relevant document answers the query or records a directly reusable decision.",
4
+ "documents": [
5
+ { "id": "db-search-scope", "project": "ph", "text": "Semantic search must apply project metadata before the nearest-neighbor result limit; otherwise unrelated vectors can hide the best in-project result." },
6
+ { "id": "capture-normalization", "project": "ph", "text": "Capture normalization shares timestamp, host, exit code, project detection, and metadata handling across direct logging, wrappers, and history importers." },
7
+ { "id": "filter-policy", "project": "ph", "text": "TUI filter policy is pure: metadata parsing, active filtering, distinct options, and counts are independent from Ink rendering." },
8
+ { "id": "mcp-tools", "project": "ph", "text": "The MCP server exposes project memory, project context, prompt search, prompt lookup, and chronological timeline tools over stdio." },
9
+ { "id": "claude-import", "project": "ph", "text": "Claude history import scans project JSONL transcripts, pairs each user message with the next assistant text, and skips thinking and tool blocks." },
10
+ { "id": "gemini-import", "project": "ph", "text": "Gemini history import reads session JSON, pairs human messages with the following model response, and supports dry run and duplicate filtering." },
11
+ { "id": "remote-sync", "project": "ph", "text": "Remote sync pushes unsynced prompts and pulls newer records; sync hashes deduplicate matching prompt, response, tool, and arguments." },
12
+ { "id": "analysis-memory", "project": "ph", "text": "Background analysis appends project memories and merges key insights and technical decisions into a single project summary." },
13
+ { "id": "unrelated-react", "project": "lens", "text": "React rendering uses reconciliation to compare virtual trees and update the browser DOM." },
14
+ { "id": "unrelated-go", "project": "sonic", "text": "Go goroutines communicate using channels and are scheduled by the Go runtime." }
15
+ ],
16
+ "queries": [
17
+ { "query": "Why does semantic search need to filter by project before limiting nearest neighbors?", "relevant": ["db-search-scope"] },
18
+ { "query": "Which fields and capture paths should use shared normalization?", "relevant": ["capture-normalization"] },
19
+ { "query": "Where is filter counting behavior tested separately from the terminal UI?", "relevant": ["filter-policy"] },
20
+ { "query": "What can an MCP client retrieve from ph?", "relevant": ["mcp-tools"] },
21
+ { "query": "How are assistant replies and hidden reasoning handled in Claude imports?", "relevant": ["claude-import"] },
22
+ { "query": "How does Gemini history import pair prompt and model output?", "relevant": ["gemini-import"] },
23
+ { "query": "How does ph avoid duplicate records when synchronizing laptops?", "relevant": ["remote-sync"] },
24
+ { "query": "How do prompt analyses update the long term project knowledge?", "relevant": ["analysis-memory"] }
25
+ ]
26
+ }
@@ -0,0 +1,27 @@
1
+ # Project context retrieval evaluation
2
+
3
+ Two complementary evaluations are maintained:
4
+
5
+ - `src/context/__tests__/retrieval-eval.test.ts` is a deterministic regression
6
+ test for SQLite ranking and project scoping. It uses fixed vectors and must
7
+ remain independent of external services.
8
+ - `context-retrieval-golden.json` is a small maintainer-judged set of eight
9
+ questions against ten project-history snippets, including two cross-project
10
+ distractors. The relevance labels mean that a snippet directly answers the
11
+ question or records a reusable decision. The snippets summarize documented
12
+ ph behavior, rather than using private prompt-history data.
13
+
14
+ Run the model-backed evaluation with `npm run eval:retrieval`. It uses the
15
+ configured Ollama URL and embedding model, or `PH_OLLAMA_URL` and
16
+ `PH_EMBED_MODEL` overrides, embeds the corpus and queries, and reports Recall@5,
17
+ MRR, and each ranked result. The current database schema requires 768-dimensional
18
+ vectors. Review the relevance labels when behavior or terminology changes.
19
+
20
+ The deterministic fixture currently scores Recall@2 = 1.0 and MRR = 1.0.
21
+ These are implementation-regression results, not model-quality scores. No
22
+ model-backed score is recorded until the evaluator is run against a reachable
23
+ Ollama instance and the configured embedding model.
24
+
25
+ On 2026-10-09 the configured default endpoint `http://localhost:11434` refused
26
+ connections, so this run produced no model score. Start the local embedding
27
+ server or set `PH_OLLAMA_URL` to the intended reachable endpoint, then rerun.
package/docs/hooks.md CHANGED
@@ -4,9 +4,10 @@
4
4
 
5
5
  | Tool | Type | File | Status |
6
6
  |------|------|------|--------|
7
- | Claude Code | Shell script (Stop hook) | `hooks/claude/ph-hook.sh` | ✅ |
8
- | Gemini CLI | Shell script (AfterAgent hook) | `hooks/gemini/ph-hook.sh` | ✅ |
9
- | OpenCode | JS/TS Plugin | `hooks/opencode/ph-plugin.ts` | ✅ |
7
+ | Claude Code | Shell script (Stop hook) | `hooks/claude/ph-hook.sh` | Supported |
8
+ | Codex CLI | Shell script (Stop hook) | `hooks/codex/ph-hook.sh` | Supported |
9
+ | Gemini CLI | Shell script (AfterAgent hook) | `hooks/gemini/ph-hook.sh` | Supported |
10
+ | OpenCode | TypeScript plugin | `hooks/opencode/ph-plugin.ts` | Supported |
10
11
 
11
12
  ## How Hooks Work
12
13
 
@@ -15,21 +16,25 @@ Each supported AI CLI tool exposes a native hook mechanism:
15
16
  - **Claude Code** — `Stop` hook, triggered after each agent session completes.
16
17
  Reads the JSONL transcript, extracts last user prompt + assistant response, pipes to `ph log`.
17
18
 
19
+ - **Codex CLI** — `Stop` hook receives the rollout `transcript_path`; the hook
20
+ invokes `ph import codex --file` so each completed turn is paired from the
21
+ transcript and duplicate turns are skipped.
22
+
18
23
  - **Gemini CLI** — `AfterAgent` hook, triggered after each agent turn.
19
24
  Receives JSON with `prompt` and `prompt_response` fields directly, pipes to `ph log`.
20
25
 
21
26
  - **OpenCode** — Plugin system with `chat.message` + `experimental.text.complete` hooks.
22
27
  Intercepts messages, pairs user prompts with streamed assistant responses, pipes to `ph log`.
23
28
 
24
- All hooks run in the background (`& + disown` for shell scripts; Promise fire-and-forget for the plugin).
25
- Never block the AI tool from exiting.
29
+ Shell hooks return success even when capture fails; the Codex hook performs a
30
+ small local transcript import. The OpenCode plugin uses fire-and-forget logging.
26
31
 
27
32
  ## Data Flow
28
33
 
29
34
  ```
30
35
  AI CLI Tool
31
36
  ↓ (automatic hook after each exchange)
32
- ph log (stdin JSON)
37
+ ph log or ph import codex --file <transcript>
33
38
  ↓
34
39
  SQLite (~/.prompt_history.db)
35
40
  ↓
@@ -42,4 +47,5 @@ ph browse / ph search / ph sessions
42
47
 
43
48
  ## Installation
44
49
 
45
- See `docs/ph-manual.md` for detailed installation instructions per tool.
50
+ See `hooks/codex/README.md` for Codex installation and `docs/ph-manual.md` for
51
+ the other tool setup instructions.
@@ -0,0 +1,145 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <meta name="description" content="Architecture and product direction analysis for ph, a local-first AI work memory.">
7
+ <title>ph — Product and Architecture Analysis</title>
8
+ <script src="https://cdn.tailwindcss.com"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js"></script>
10
+ <script>mermaid.initialize({ startOnLoad: true, theme: 'neutral', flowchart: { curve: 'basis' } });</script>
11
+ <style>
12
+ :root { --ink:#17212b; --paper:#f6f7f5; --teal:#0f766e; --rose:#be123c; --amber:#b45309; }
13
+ body { background:var(--paper); color:var(--ink); font-family:Inter,ui-sans-serif,system-ui,-apple-system,sans-serif; }
14
+ h1,h2,h3,.serif { font-family:Georgia,Cambria,serif; }
15
+ .module-box { border:1px solid #cbd5e1; border-radius:14px; background:white; padding:1rem; }
16
+ .diagram-arrow { color:#64748b; font-size:1.4rem; align-self:center; }
17
+ .seam-line { border-left:2px dashed #0f766e; padding-left:1rem; }
18
+ .deep { background:#134e4a; color:#ecfdf5; border-color:#0f766e; }
19
+ .leak { border:1px dashed #e11d48; background:#fff1f2; color:#881337; }
20
+ .source { font: .82rem ui-monospace,SFMono-Regular,monospace; color:#475569; }
21
+ @media (max-width:700px) { .diagram-arrow { transform:rotate(90deg); } }
22
+ </style>
23
+ </head>
24
+ <body>
25
+ <header class="bg-slate-950 text-slate-100">
26
+ <div class="mx-auto max-w-6xl px-6 py-14">
27
+ <p class="text-sm uppercase tracking-[.2em] text-teal-300">Product and architecture decision</p>
28
+ <h1 class="serif mt-3 text-5xl font-semibold">ph: from prompt archive to AI work memory</h1>
29
+ <p class="mt-5 max-w-3xl text-lg text-slate-300">A source-grounded review of what the application can do now, where its architecture concentrates change, and which next step has the best leverage.</p>
30
+ <div class="mt-8 grid gap-3 border-l-2 border-teal-400 pl-4 text-lg">
31
+ <p><strong>Strength:</strong> a local SQLite store feeds several useful surfaces: CLI, TUI, MCP, and optional HTTP sync.</p>
32
+ <p><strong>Largest remaining flaw:</strong> BrowseApp still owns several views and application state. Importers, MCP, filter transitions, browser keyboard navigation, and interactive wrapped prompt/response capture now have focused coverage.</p>
33
+ </div>
34
+ <div class="mt-8 flex flex-wrap gap-3 text-sm"><span class="rounded-full bg-slate-800 px-3 py-1">Module</span><span class="rounded-full bg-teal-800 px-3 py-1">Seam</span><span class="rounded-full bg-rose-900 px-3 py-1">Leakage</span><span class="rounded-full bg-emerald-900 px-3 py-1">Deep Module</span></div>
35
+ <p class="mt-7 text-sm text-slate-400">Review date: 2026-10-09 · Working tree: modified by this review's follow-up implementation</p>
36
+ </div>
37
+ </header>
38
+
39
+ <main class="mx-auto max-w-6xl space-y-16 px-6 py-12">
40
+ <section>
41
+ <h2 class="serif text-3xl font-semibold">Current posture</h2>
42
+ <p class="mt-3 max-w-4xl text-slate-700">The product already has a coherent local-first core: capture conversations, attach project metadata, search them, derive summaries, then expose the result to people and agents. Its feature surface is broad; the next architectural gain comes from making retrieval behavior consistent and easy to evaluate.</p>
43
+ <div class="mt-6 grid gap-4 sm:grid-cols-3">
44
+ <div class="module-box"><div class="text-3xl font-semibold text-teal-800">432</div><div class="mt-1 text-sm">lines in CLI entrypoint <code>src/cli.ts</code></div></div>
45
+ <div class="module-box"><div class="text-3xl font-semibold text-teal-800">8,347</div><div class="mt-1 text-sm">non-test TypeScript implementation lines</div></div>
46
+ <div class="module-box"><div class="text-3xl font-semibold text-teal-800">11</div><div class="mt-1 text-sm">test files in the current source tree</div></div>
47
+ </div>
48
+ <p class="mt-4 text-sm text-slate-600">Evidence: current file counts and line counts, not the older figures copied into project docs. `SPEC-INDEX.md` lists 15 reverse-engineered baseline specifications, all marked implemented; those specs describe current behavior, not a committed forward roadmap.</p>
49
+ </section>
50
+
51
+ <section>
52
+ <h2 class="serif text-3xl font-semibold">Runtime map</h2>
53
+ <p class="mt-2 text-slate-700">The main path runs from heterogeneous capture adapters through SQLite to multiple consumers. LLM analysis and embedding generation add local-model or API calls on selected paths.</p>
54
+ <div class="module-box mt-6 overflow-x-auto">
55
+ <pre class="mermaid">flowchart LR
56
+ subgraph Capture["Capture and import"]
57
+ Hooks["Claude, Codex, and Gemini hooks"]
58
+ Plugin["OpenCode plugin"]
59
+ Wrap["CLI and PTY wrapper"]
60
+ Import["History importers"]
61
+ end
62
+ Normalize["Filtering and metadata"]
63
+ Store["SQLite: prompts, FTS5, vectors, memory, archive"]
64
+ Analysis["LLM analysis and summary updates"]
65
+ Embed["Ollama embedding adapter"]
66
+ Retrieve["Project context retrieval and formatting"]
67
+ CLI["CLI: search, context, timeline"]
68
+ Chat["Context-injected chat"]
69
+ MCP["MCP tools"]
70
+ TUI["Ink browser"]
71
+ HTTP["HTTP API and remote sync"]
72
+ Hooks --> Normalize
73
+ Plugin --> Normalize
74
+ Wrap --> Normalize
75
+ Import --> Normalize
76
+ Normalize --> Store
77
+ Store --> Analysis
78
+ Analysis --> Store
79
+ Store --> Embed
80
+ Embed --> Store
81
+ Store --> Retrieve
82
+ Retrieve --> CLI
83
+ Retrieve --> Chat
84
+ Retrieve --> MCP
85
+ Store --> TUI
86
+ Store --> HTTP
87
+ classDef deep fill:#134e4a,stroke:#0f766e,color:#ecfdf5,stroke-width:2px
88
+ classDef leak fill:#fff1f2,stroke:#e11d48,color:#881337,stroke-dasharray:5 4
89
+ classDef seam fill:#ecfeff,stroke:#0f766e,color:#134e4a,stroke-dasharray:3 3
90
+ class Store,Normalize deep
91
+ class Retrieve seam
92
+ class CLI,Chat,MCP leak</pre>
93
+ </div>
94
+ <p class="mt-3 source">Evidence: src/cli.ts; src/commands/log.ts; src/commands/context.ts; src/commands/chat.ts; src/mcp/server.ts; src/db/index.ts; src/server/index.ts; hooks/</p>
95
+ </section>
96
+
97
+ <section>
98
+ <h2 class="serif text-3xl font-semibold">Tradeoffs and decision record</h2>
99
+ <div class="mt-5 overflow-x-auto rounded-xl border border-slate-300 bg-white">
100
+ <table class="w-full min-w-[760px] text-left text-sm"><thead class="bg-slate-100"><tr><th class="p-3">Option</th><th class="p-3">Pros</th><th class="p-3">Costs and risks</th><th class="p-3">Recommendation</th></tr></thead><tbody class="divide-y divide-slate-200">
101
+ <tr><td class="p-3 font-semibold">A. Consolidate context retrieval first</td><td class="p-3">Makes CLI, chat, and MCP return consistent evidence; creates one seam to test ranking, scope, and output.</td><td class="p-3">Needs careful migration of consumer-specific options and stable output expectations.</td><td class="p-3 text-teal-800">Chosen and implemented</td></tr>
102
+ <tr><td class="p-3 font-semibold">B. Rework SQLite and PhDB boundaries first</td><td class="p-3">Could make storage easier to replace and lower database coupling.</td><td class="p-3">Broad 814-line store surface; risks a large refactor before validating the product's central retrieval behavior.</td><td class="p-3">Defer</td></tr>
103
+ <tr><td class="p-3 font-semibold">C. Add more capture integrations first</td><td class="p-3">More tools and histories become available quickly.</td><td class="p-3">Increases ingestion breadth while current capture paths have limited integration coverage and context remains inconsistent.</td><td class="p-3">Defer until quality baseline</td></tr>
104
+ <tr><td class="p-3 font-semibold">D. Turn it into a hosted sync product</td><td class="p-3">Central access across devices and teams.</td><td class="p-3">Authentication, transport, privacy, conflict policy, operations, and support expand the product substantially.</td><td class="p-3">Keep optional and personal for now</td></tr>
105
+ </tbody></table>
106
+ </div>
107
+ <div class="seam-line mt-6 rounded-r-xl bg-teal-50 p-5"><h3 class="serif text-xl font-semibold text-teal-950">Decision record · 2026-10-09</h3><p class="mt-2"><strong>Chosen:</strong> treat `ph` as a local-first AI work memory and make shared project-context retrieval the first architectural move. Status: implemented for CLI, chat, and MCP; project-scoped semantic lookup now filters before the final result limit.</p><p class="mt-2"><strong>Why:</strong> a shared retrieval seam makes source selection consistent and creates a place to evaluate evidence ranking. The deterministic fixture currently reports Recall@2 = 1.0 and MRR = 1.0 on synthetic vectors; this does not measure real embedding relevance.</p><p class="mt-2"><strong>Not decided:</strong> hosted/team sync, a GUI beyond the existing TUI, and any replacement database. These need separate product decisions.</p></div>
108
+ <div class="mt-5 rounded-xl border border-amber-300 bg-amber-50 p-5"><h3 class="font-semibold text-amber-950">Cost, rate limits, and latency</h3><p class="mt-2 text-sm text-amber-950">Plain text search and local SQLite reads need no model call. Semantic context and MCP semantic search call the configured Ollama embedding endpoint; unavailable or slow Ollama can delay or fail those paths. Background analysis calls the selected Ollama or Gemini provider, so Gemini usage may incur provider cost and rate limits; enabling it makes each captured interaction eligible for asynchronous analysis. Keep these calls optional, expose failure/latency clearly, and avoid repeating embedding calls when an equivalent vector is already available.</p><p class="source mt-2">Evidence: src/commands/context.ts:26-37; src/mcp/server.ts:305-328; src/embedding/index.ts:5-33; src/analyzer/index.ts:119-129; src/background/analyzer.ts.</p></div>
109
+ </section>
110
+
111
+ <section>
112
+ <h2 class="serif text-3xl font-semibold">Candidates for deepening</h2>
113
+ <div class="mt-6 space-y-7">
114
+ <article class="module-box"><div class="flex flex-wrap items-center gap-2"><h3 class="serif text-xl font-semibold">1. Shared project-context retrieval</h3><span class="rounded-full bg-teal-100 px-2 py-1 text-xs text-teal-900">Strong · P0</span></div><p class="source mt-2">src/commands/context.ts:22-89 · src/commands/chat.ts:21-65 · src/mcp/server.ts:305-402</p><p class="mt-3"><strong>Problem.</strong> Consumers independently select memories/prompts, filter projects, and assemble Markdown. The chat path uses recent prompts while the MCP context path combines summary, memories, and interactions; output meaning can drift.</p><p class="mt-2"><strong>Solution.</strong> Deepen a context retrieval module behind a Seam that accepts project, query, limits, and source preferences, then returns structured evidence. Keep CLI, chat, and MCP as thin renderers/adapters.</p><div class="mt-4 grid gap-3 md:grid-cols-[1fr_auto_1fr]"><div class="module-box leak"><strong>Before</strong><p class="mt-2">CLI retrieval + formatter<br>Chat retrieval + formatter<br>MCP retrieval + formatter</p></div><div class="diagram-arrow">→</div><div class="module-box deep"><strong>After</strong><p class="mt-2">One retrieval Seam → structured evidence → CLI / chat / MCP renderers</p></div></div><div class="mt-4 grid gap-2 text-sm md:grid-cols-3"><div><strong>Leverage:</strong> consistent answers across three consumers.</div><div><strong>Locality:</strong> ranking and evidence assembly live together.</div><div><strong>Tests:</strong> test retrieval once, then thin adapter contracts.</div></div></article>
115
+
116
+ <article class="module-box"><div class="flex flex-wrap items-center gap-2"><h3 class="serif text-xl font-semibold">2. PhDB capability boundary</h3><span class="rounded-full bg-amber-100 px-2 py-1 text-xs text-amber-900">Worth exploring · P1</span></div><p class="source mt-2">src/db/index.ts:12-814 · src/server/index.ts:68-201 · src/commands/remote.ts</p><p class="mt-3"><strong>Problem.</strong> One 814-line class owns schema migration, SQL, search, memory summaries, archive, and sync-specific queries. The HTTP server and commands depend on this broad concrete class.</p><p class="mt-2"><strong>Solution.</strong> After the context seam exists, identify the smallest storage capabilities needed by retrieval and sync. Extract only where a real consumer boundary becomes clearer; preserve SQLite as the default implementation.</p><div class="mt-4 grid gap-3 md:grid-cols-[1fr_auto_1fr]"><div class="module-box leak"><strong>Before</strong><p class="mt-2">Commands and servers reach a broad PhDB surface</p></div><div class="diagram-arrow">→</div><div class="module-box deep"><strong>After</strong><p class="mt-2">Narrow query capabilities behind explicit storage seams</p></div></div><div class="mt-4 grid gap-2 text-sm md:grid-cols-3"><div><strong>Leverage:</strong> isolate persistence changes.</div><div><strong>Locality:</strong> keep SQL details within storage.</div><div><strong>Tests:</strong> contract tests for query behavior.</div></div></article>
117
+
118
+ <article class="module-box"><div class="flex flex-wrap items-center gap-2"><h3 class="serif text-xl font-semibold">3. TUI view and state boundaries</h3><span class="rounded-full bg-amber-100 px-2 py-1 text-xs text-amber-900">Worth exploring · P1</span></div><p class="source mt-2">src/ui/BrowseApp.tsx (1,183 lines) · src/ui/{Header,Footer,ListEntry,PreviewPane,SearchBar}.tsx</p><p class="mt-3"><strong>Problem.</strong> BrowseApp still hosts list, detail, filters, settings, and interaction state in one large component. Changes in one view have weak Locality and are harder to isolate from terminal rendering.</p><p class="mt-2"><strong>Solution.</strong> Deepen the browser around a small state model and view-specific components, preserving Ink as the rendering adapter. Prioritize only seams that enable independent interaction tests.</p><div class="mt-4 grid gap-3 md:grid-cols-[1fr_auto_1fr]"><div class="module-box leak"><strong>Before</strong><p class="mt-2">One component coordinates all browser views</p></div><div class="diagram-arrow">→</div><div class="module-box deep"><strong>After</strong><p class="mt-2">Browser state seam with local list, detail, filter, and settings views</p></div></div><div class="mt-4 grid gap-2 text-sm md:grid-cols-3"><div><strong>Leverage:</strong> safer browser feature work.</div><div><strong>Locality:</strong> view logic beside its UI.</div><div><strong>Tests:</strong> focused interaction coverage.</div></div></article>
119
+
120
+ <article class="module-box"><div class="flex flex-wrap items-center gap-2"><h3 class="serif text-xl font-semibold">4. Capture adapter contract and coverage</h3><span class="rounded-full bg-amber-100 px-2 py-1 text-xs text-amber-900">Worth exploring · P1</span></div><p class="source mt-2">src/commands/log.ts · src/runner/{inline,project,git-context}.ts · src/pty/wrapper.ts · src/importer/*.ts · hooks/</p><p class="mt-3"><strong>Problem.</strong> Capture spans wrappers, shell hooks, a plugin, stdin logging, and importers. Their external payloads and pairing rules vary, while the test inventory is small relative to the integration surface.</p><p class="mt-2"><strong>Solution.</strong> Define and validate one normalized capture record at the ingestion boundary, then keep each provider-specific adapter responsible for parsing its source format. Add contract fixtures for adapters as they are actively supported.</p><div class="mt-4 grid gap-3 md:grid-cols-[1fr_auto_1fr]"><div class="module-box leak"><strong>Before</strong><p class="mt-2">Many source formats flow into similar but uneven paths</p></div><div class="diagram-arrow">→</div><div class="module-box deep"><strong>After</strong><p class="mt-2">Provider adapters → validated capture record → filter and storage</p></div></div><div class="mt-4 grid gap-2 text-sm md:grid-cols-3"><div><strong>Leverage:</strong> reliable capture across tools.</div><div><strong>Locality:</strong> source parsing stays at adapter edges.</div><div><strong>Tests:</strong> fixture contracts reveal upstream drift.</div></div></article>
121
+ </div>
122
+ </section>
123
+
124
+ <section>
125
+ <h2 class="serif text-3xl font-semibold">Top recommendation</h2>
126
+ <div class="mt-4 rounded-xl bg-slate-900 p-6 text-slate-100"><p class="text-lg"><strong>Delivered: shared project-context retrieval and focused verification.</strong></p><p class="mt-3 text-slate-300">CLI context, chat, and MCP share structured retrieval and Markdown formatting. Project filtering now happens before the result limit. The deterministic regression fixture reports Recall@2 = 1.0 and MRR = 1.0; the maintainer-judged model evaluation is runnable with <code>npm run eval:retrieval</code> and requires a reachable 768-dimensional Ollama embedding model.</p><p class="mt-3 text-slate-300">Capture normalization, TUI filter policy, importer fixtures, MCP tool calls, and PTY response cleanup now have focused tests. Vector encoding, compatibility storage, and ranking now live in SemanticIndex while PhDB retains its public methods. Further splits wait for a second adapter or an independent migration seam.</p></div>
127
+ </section>
128
+
129
+ <section>
130
+ <h2 class="serif text-3xl font-semibold">What ph can do today</h2>
131
+ <div class="mt-5 grid gap-4 sm:grid-cols-2">
132
+ <div class="module-box"><h3 class="font-semibold">Capture and import</h3><p class="mt-2 text-sm">Wrap a CLI tool, accept direct `ph log` input, use Claude/Codex/Gemini hooks or the OpenCode plugin, and import histories from all four tools.</p><p class="source mt-3">src/commands/{wrap,log,import}.ts · hooks/ · src/importer/</p></div>
133
+ <div class="module-box"><h3 class="font-semibold">Search and browse</h3><p class="mt-2 text-sm">Use FTS and filters, semantic search when vectors exist, archive search, and the Ink TUI to inspect, star, edit, or rerun entries.</p><p class="source mt-3">src/commands/search.ts · src/db/index.ts · src/ui/BrowseApp.tsx</p></div>
134
+ <div class="module-box"><h3 class="font-semibold">Build project knowledge</h3><p class="mt-2 text-sm">Analyze captured interactions with Ollama or Gemini, accumulate summaries and decisions, view project timelines, and produce pipe-ready context.</p><p class="source mt-3">src/analyzer/ · src/commands/{analyze,context,timeline}.ts · src/db/index.ts</p></div>
135
+ <div class="module-box"><h3 class="font-semibold">Connect agents and machines</h3><p class="mt-2 text-sm">Expose MCP tools over stdio and run an optional HTTP API for prompt search and push/pull synchronization.</p><p class="source mt-3">src/mcp/server.ts · src/server/index.ts · src/commands/remote.ts</p></div>
136
+ </div>
137
+ <div class="mt-6 grid gap-4 md:grid-cols-2">
138
+ <div class="rounded-xl border border-teal-300 bg-teal-50 p-5"><h3 class="font-semibold text-teal-950">Ready for...</h3><p class="mt-2 text-sm text-teal-950">Personal local prompt history, manual retrieval, agent queries through MCP, and optional single-user machine sync, provided the configured local database and embedding/analysis services are available for the selected features.</p></div>
139
+ <div class="rounded-xl border border-amber-300 bg-amber-50 p-5"><h3 class="font-semibold text-amber-950">Still requires integration...</h3><p class="mt-2 text-sm text-amber-950">Reliable out-of-the-box cross-tool capture, consistent context quality across consumers, and shared/team hosted memory. Specifications establish a broad implemented baseline, but not product-level evidence for every external tool version or operational deployment.</p></div>
140
+ </div>
141
+ </section>
142
+ </main>
143
+ <footer class="border-t border-slate-300 bg-white"><div class="mx-auto max-w-6xl px-6 py-6 text-sm text-slate-600">Created: 2026-10-09 · Updated: 2026-10-09 · Evidence source: inspected ph working tree and docs/specs baseline</div></footer>
144
+ </body>
145
+ </html>