@gi4nks/ph 1.6.0 → 1.8.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 (33) hide show
  1. package/CHANGELOG.md +22 -1
  2. package/LICENSE +1 -1
  3. package/README.md +79 -19
  4. package/dist/cli.js +3593 -3677
  5. package/dist/cli.js.map +1 -1
  6. package/docs/evals/context-retrieval-golden.json +17 -1
  7. package/docs/ph-architecture-review.html +179 -0
  8. package/docs/ph-manual.md +129 -73
  9. package/docs/ph-operational-memory-analysis.html +104 -0
  10. package/docs/plans/2026-10-10-operational-memory.md +192 -0
  11. package/docs/specs/SPEC-001-architecture-cli.md +100 -72
  12. package/docs/specs/SPEC-002-database-layer.md +22 -3
  13. package/docs/specs/SPEC-003-capture-modes.md +22 -9
  14. package/docs/specs/SPEC-005-search.md +46 -11
  15. package/docs/specs/SPEC-006-analysis-pipeline.md +8 -6
  16. package/docs/specs/SPEC-007-memory-summaries.md +19 -19
  17. package/docs/specs/SPEC-008-embeddings.md +8 -2
  18. package/docs/specs/SPEC-009-retention-archive.md +2 -2
  19. package/docs/specs/SPEC-010-remote-sync.md +77 -103
  20. package/docs/specs/SPEC-011-mcp-server.md +7 -4
  21. package/docs/specs/SPEC-012-tui-browser.md +30 -96
  22. package/docs/specs/SPEC-015-config-env.md +4 -0
  23. package/docs/specs/SPEC-016-operational-memory.md +48 -0
  24. package/docs/specs/SPEC-017-architecture-consolidation.md +63 -0
  25. package/docs/specs/SPEC-018-interaction-inspection-and-recall-integrity.md +164 -0
  26. package/docs/specs/SPEC-019-network-capture-and-ranking-integrity.md +36 -0
  27. package/docs/specs/SPEC-INDEX.md +12 -7
  28. package/docs/specs/SPEC-ISSUES.md +104 -18
  29. package/hooks/claude/README.md +1 -1
  30. package/hooks/codex/README.md +1 -1
  31. package/hooks/codex/ph-hook.sh +2 -1
  32. package/hooks/gemini/README.md +1 -1
  33. package/package.json +6 -7
@@ -10,6 +10,14 @@
10
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
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
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": "shared-context", "project": "ph", "text": "getProjectContext and formatProjectContext are shared by ph context, chat, and MCP; semantic retrieval must stay project scoped." },
14
+ { "id": "wise-provider", "project": "ph", "text": "Wise provides OpenRouter and MLX-Serve providers in ph; provider and model configuration is shared across CLI and TUI." },
15
+ { "id": "homo-provider-boundary", "project": "homo", "text": "HOMO uses the shared Wise library to configure multiple AI providers behind the application's AI integration." },
16
+ { "id": "homo-genesis-context", "project": "homo", "text": "Chapter Genesis carries previous content fragments and book-level lore constraints into generated scenes." },
17
+ { "id": "picot-sqlite-build", "project": "picot", "text": "PicoT uses SQLite and Next.js; builds should use a SQLite timeout and isolated build data to avoid SQLITE_BUSY races." },
18
+ { "id": "picot-breadcrumb-context", "project": "picot", "text": "PicoT document preview preserves the originating library listing, search, and filters through breadcrumb navigation." },
19
+ { "id": "lens-harness-goal", "project": "lens", "text": "Lens integrates the harness goal loop with verified predicates, progress, recovery, and a run_command tool." },
20
+ { "id": "lens-wise-provider", "project": "lens", "text": "Lens WiseProvider supports OpenRouter and MLX-Serve using configured provider model IDs." },
13
21
  { "id": "unrelated-react", "project": "lens", "text": "React rendering uses reconciliation to compare virtual trees and update the browser DOM." },
14
22
  { "id": "unrelated-go", "project": "sonic", "text": "Go goroutines communicate using channels and are scheduled by the Go runtime." }
15
23
  ],
@@ -21,6 +29,14 @@
21
29
  { "query": "How are assistant replies and hidden reasoning handled in Claude imports?", "relevant": ["claude-import"] },
22
30
  { "query": "How does Gemini history import pair prompt and model output?", "relevant": ["gemini-import"] },
23
31
  { "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"] }
32
+ { "query": "How do prompt analyses update the long term project knowledge?", "relevant": ["analysis-memory"] },
33
+ { "query": "Which shared retrieval API do CLI, chat, and MCP use?", "relevant": ["shared-context"] },
34
+ { "query": "How are Wise models and providers configured in ph?", "relevant": ["wise-provider"] },
35
+ { "query": "How does HOMO pass earlier chapter context and lore into generation?", "relevant": ["homo-genesis-context"] },
36
+ { "query": "Which provider abstraction does HOMO use for AI backends?", "relevant": ["homo-provider-boundary"] },
37
+ { "query": "How should PicoT builds avoid SQLite locking conflicts?", "relevant": ["picot-sqlite-build"] },
38
+ { "query": "What state does PicoT preserve when navigating back from a document?", "relevant": ["picot-breadcrumb-context"] },
39
+ { "query": "How does Lens verify and recover an agent goal?", "relevant": ["lens-harness-goal"] },
40
+ { "query": "Which local and hosted AI providers are available to Lens?", "relevant": ["lens-wise-provider"] }
25
41
  ]
26
42
  }
@@ -0,0 +1,179 @@
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
+ <title>PH Architecture Review</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js"></script>
9
+ <style>
10
+ :root { color-scheme: light; --ink:#17212b; --muted:#52616d; --line:#d9e1e5; --paper:#f5f7f6; --teal:#087f74; --amber:#a85c05; --rose:#bd3e4b; }
11
+ body { background:var(--paper); color:var(--ink); font-family:Inter,ui-sans-serif,system-ui,-apple-system,sans-serif; }
12
+ h1,h2,h3,h4,.serif { font-family:Georgia,Cambria,"Times New Roman",serif; }
13
+ .module-box { border:1px solid #a8b8bf; border-radius:1rem; padding:1rem; background:#fff; box-shadow:0 10px 30px #162a3010; }
14
+ .diagram-arrow { color:#73848c; font-size:1.35rem; line-height:1; }
15
+ .seam-line { border-top:2px dashed var(--teal); position:relative; }
16
+ .seam-line:after { content:"SEAM"; position:absolute; right:0; top:-.78rem; padding:0 .45rem; background:white; color:var(--teal); font-size:.65rem; font-weight:800; letter-spacing:.12em; }
17
+ .mermaid { overflow-x:auto; background:#fff; padding:1.25rem; border:1px solid var(--line); border-radius:1rem; }
18
+ .evidence { font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:.8rem; overflow-wrap:anywhere; }
19
+ .impact td,.impact th { padding:.55rem .65rem; border-bottom:1px solid var(--line); text-align:left; vertical-align:top; }
20
+ @media print { body { background:white; } .module-box,.mermaid { box-shadow:none; break-inside:avoid; } }
21
+ </style>
22
+ </head>
23
+ <body>
24
+ <main class="max-w-6xl mx-auto px-5 sm:px-8 py-10 sm:py-16">
25
+ <header class="border-b border-slate-300 pb-10">
26
+ <div class="flex flex-wrap gap-3 items-center text-sm text-slate-600">
27
+ <span class="rounded-full bg-slate-200 px-3 py-1 font-semibold">PH · PROMPT HISTORY</span>
28
+ <span>Architecture review</span><span>22 October 2026</span>
29
+ <span class="rounded-full bg-amber-100 text-amber-900 px-3 py-1 font-semibold">Working tree dirty</span>
30
+ </div>
31
+ <h1 class="serif text-5xl sm:text-6xl mt-8 leading-tight">A useful core under too many surfaces</h1>
32
+ <p class="mt-7 text-xl sm:text-2xl font-bold max-w-4xl">Strength: local capture, SQLite storage, and project-scoped retrieval form a coherent foundation with useful seams.</p>
33
+ <p class="mt-3 text-xl sm:text-2xl font-bold text-rose-800 max-w-4xl">Flaw: PH keeps adding command, transport, and knowledge workflows faster than it proves which ones users need.</p>
34
+ <div class="flex flex-wrap gap-3 mt-8 text-sm">
35
+ <span class="rounded-lg bg-slate-800 text-white px-3 py-2">Module</span>
36
+ <span class="rounded-lg border-2 border-dashed border-teal-700 text-teal-900 px-3 py-2">Seam</span>
37
+ <span class="rounded-lg border-2 border-dashed border-rose-600 text-rose-800 px-3 py-2">Leakage / unwired</span>
38
+ <span class="rounded-lg bg-teal-800 text-white px-3 py-2">Deep Module</span>
39
+ </div>
40
+ <p class="mt-6 max-w-4xl text-slate-600">This review describes the current working tree, including uncommitted operational-memory changes. It does not treat documentation or a passing test suite as proof of adoption.</p>
41
+ </header>
42
+
43
+ <section class="py-12 border-b border-slate-300">
44
+ <h2 class="serif text-3xl">Current Posture</h2>
45
+ <p class="mt-4 max-w-4xl text-slate-700">PH has a strong local-first data path and a meaningful retrieval boundary. Prompt capture remains useful without an LLM; semantic retrieval is optional; user approval gates curated memory writes. In this pass the MCP composition root was reduced to protocol setup, while memory and archive SQL moved behind repositories. The remaining concern is scope: a broad command set still exceeds what the operational workflow has validated.</p>
46
+ <div class="grid md:grid-cols-3 gap-4 mt-7">
47
+ <div class="module-box"><div class="text-3xl font-bold">97</div><div class="text-sm text-slate-600 mt-1">TypeScript / TSX source files</div></div>
48
+ <div class="module-box"><div class="text-3xl font-bold">17</div><div class="text-sm text-slate-600 mt-1">Test files; 94 tests passed in this checkout</div></div>
49
+ <div class="module-box"><div class="text-3xl font-bold">482 · 50 · 521 · 964</div><div class="text-sm text-slate-600 mt-1">Lines in CLI, MCP composition root, PhDB facade, and BrowseApp respectively</div></div>
50
+ </div>
51
+ <div class="mt-6 grid md:grid-cols-2 gap-5 text-sm">
52
+ <div class="rounded-xl border border-slate-300 bg-white p-5"><h3 class="font-bold text-teal-900">Rules the system respects</h3><ul class="list-disc pl-5 mt-3 space-y-1 text-slate-700"><li>SQLite is the source of truth; Ollama and generative providers are optional.</li><li>Project filters are applied inside semantic retrieval before limiting results.</li><li>Operational `prepare` is read-only; `close` asks for approval before promotion.</li><li>CLI and MCP share task-context retrieval and atomic memory promotion use cases.</li><li>Memory and archive repositories share the existing SQLite connection through the stable PhDB facade.</li></ul></div>
53
+ <div class="rounded-xl border border-rose-200 bg-rose-50 p-5"><h3 class="font-bold text-rose-900">Rules that are not yet proven</h3><ul class="list-disc pl-5 mt-3 space-y-1 text-slate-700"><li>The plan's three real tasks across different projects are not evidenced; it records one temporary-database usage check.</li><li>MCP-only tools still own some search and rendering decisions inside their grouped handler modules.</li><li>Feature breadth spans history capture, analysis, memory, TUI, MCP, import, archive, and remote sync.</li><li>Embedding-backed retrieval quality has not been evaluated in this pass.</li></ul></div>
54
+ </div>
55
+ <p class="mt-5 text-sm text-slate-600">Verification observed: <span class="font-semibold">npm test</span> passed (17 files, 94 tests), <span class="font-semibold">npm run lint</span>, <span class="font-semibold">npm run build</span>, and `npx tsc --noEmit` all passed. A separate embedding-backed retrieval evaluation was not run.</p>
56
+ </section>
57
+
58
+ <section class="py-12 border-b border-slate-300">
59
+ <h2 class="serif text-3xl">Runtime Map</h2>
60
+ <p class="mt-3 max-w-4xl text-slate-700">Solid teal marks high-leverage modules; dashed red marks broad adapters or duplicated routes where responsibilities leak across boundaries.</p>
61
+ <div class="mermaid mt-6">
62
+ flowchart LR
63
+ User[User / agent] --> CLI[CLI dispatch and commands]
64
+ Hooks[CLI hooks and importers] --> Capture[Capture normalization]
65
+ CLI --> Capture
66
+ Capture --> DB[(SQLite / PhDB)]
67
+ CLI --> Retrieval[Project context retrieval]
68
+ MCP[MCP protocol composition] --> MCPTools[Grouped prompt, project, timeline handlers]
69
+ MCPTools --> Retrieval
70
+ Retrieval --> DB
71
+ Retrieval --> Embed[Embedding endpoint]
72
+ Retrieval --> Render[Shared context formatter]
73
+ Render --> CLI
74
+ Render --> MCPTools
75
+ CLI --> Close[Close proposal and approval]
76
+ Close --> Provider[Analysis provider]
77
+ Close --> DB
78
+ MCPTools --> DB
79
+ DB --> Vec[Semantic index]
80
+ CLI --> TUI[Ink browser]
81
+ TUI --> DB
82
+ CLI --> Remote[HTTP sync client]
83
+ Remote --> Server[HTTP sync server]
84
+ Server --> DB
85
+ classDef deep fill:#075e57,stroke:#064e48,color:#fff,stroke-width:2px;
86
+ classDef module fill:#e6f4f1,stroke:#0c8276,color:#153b38,stroke-width:1.5px;
87
+ classDef leak fill:#fff0f1,stroke:#c2414c,color:#762631,stroke-width:2px,stroke-dasharray:6 4;
88
+ classDef external fill:#f1f5f9,stroke:#64748b,color:#1e293b;
89
+ class Capture,Retrieval,Render,Vec deep;
90
+ class CLI,Close,TUI,DB,MCP,MCPTools module;
91
+ class Remote,Server leak;
92
+ class User,Hooks,Embed,Provider external;
93
+ </div>
94
+ <div class="grid md:grid-cols-3 gap-4 mt-5 text-sm">
95
+ <div class="module-box"><b>Capture Seam</b><p class="mt-2 text-slate-600">`src/capture/index.ts` normalizes direct logging, wrappers, and importers before persistence.</p></div>
96
+ <div class="module-box"><b>Retrieval Seam</b><p class="mt-2 text-slate-600">`src/knowledge/task-context.ts` shares bounded task retrieval across prepare and MCP; `src/context/index.ts` serves context and chat formatting.</p></div>
97
+ <div class="module-box border-rose-300"><b>Persistence Leakage</b><p class="mt-2 text-slate-600">The stable `PhDB` facade still exposes a broad prompt API; repository interfaces remain internal and SQLite-specific.</p></div>
98
+ </div>
99
+ </section>
100
+
101
+ <section class="py-12 border-b border-slate-300">
102
+ <h2 class="serif text-3xl">Candidates / Opportunities for Deepening</h2>
103
+ <p class="mt-3 text-slate-700 max-w-4xl">These are targeted reductions in real Leakage. They are not a proposal to replace the stack or split every file.</p>
104
+
105
+ <article class="mt-8 rounded-2xl border border-rose-200 bg-white p-6 sm:p-8">
106
+ <div class="flex flex-wrap justify-between gap-3"><h3 class="serif text-2xl">1. Contain product scope until real-use evidence exists</h3><div class="flex gap-2"><span class="rounded-full bg-teal-100 text-teal-900 px-3 py-1 text-sm font-bold">Implemented as a scope gate</span><span class="rounded-full bg-slate-800 text-white px-3 py-1 text-sm font-bold">P0</span></div></div>
107
+ <p class="evidence mt-4 text-slate-600">Evidence: `src/cli.ts:46-155` advertises a wide command set; `src/commands/` has 26 handlers; `README.md` describes capture, imports, analysis, memories, TUI, MCP, archive, and remote sync; `ROADMAP.md` now gates new user-facing work on three real tasks across projects.</p>
108
+ <h4 class="mt-5 font-bold">Problem</h4><p class="text-slate-700">PH now has several overlapping ways to retrieve project knowledge (`context`, `prepare`, chat injection, MCP knowledge checks) plus a separate curation flow. The tool's command count is growing while the core promise—capture useful history and find it again—has no adoption or success measure in the repo. This is product-scope Leakage: every surface needs help, docs, compatibility, and tests.</p>
109
+ <h4 class="mt-5 font-bold">Solution</h4><p class="text-slate-700">Keep the current commands available, state their distinct jobs, and defer new commands, transports, or knowledge workflows until the `prepare → work → close → promote` loop is used on three real tasks in different projects. The gate is now recorded in `ROADMAP.md`; no existing capability was removed.</p>
110
+ <div class="grid sm:grid-cols-2 gap-3 mt-5"><div class="module-box border-rose-300"><b>Before · surface area</b><div class="mt-3 flex flex-wrap gap-2 text-xs"><span class="bg-rose-50 p-2 rounded">context</span><span class="bg-rose-50 p-2 rounded">prepare</span><span class="bg-rose-50 p-2 rounded">chat context</span><span class="bg-rose-50 p-2 rounded">MCP check</span><span class="bg-rose-50 p-2 rounded">close</span><span class="bg-rose-50 p-2 rounded">save decision</span></div></div><div class="module-box border-teal-700"><b>After · gated growth</b><div class="mt-3 flex items-center gap-2 text-xs"><span class="bg-teal-50 p-2 rounded">capture</span><span class="diagram-arrow">→</span><span class="bg-teal-50 p-2 rounded">retrieve evidence</span><span class="diagram-arrow">→</span><span class="bg-teal-50 p-2 rounded">curate if useful</span></div><p class="mt-2 text-xs text-teal-900">No new surface until real-use gate.</p></div></div>
111
+ <div class="seam-line mt-8"></div><p class="mt-4 text-sm text-slate-700"><b>Seam:</b> a user-visible workflow contract that works through CLI and MCP without duplicating domain decisions. <b>Deep Module:</b> the smallest evidence-backed workflow PH can make dependable.</p>
112
+ <table class="impact w-full mt-4 text-sm"><tr><th>Leverage</th><th>Locality</th><th>Tests</th></tr><tr><td>Less maintenance per feature and clearer product promise.</td><td>Related user actions converge on fewer entry points.</td><td>Add outcome checks for retrieval usefulness and accepted promotions, not just command behavior.</td></tr></table>
113
+ </article>
114
+
115
+ <article class="mt-6 rounded-2xl border border-amber-200 bg-white p-6 sm:p-8">
116
+ <div class="flex flex-wrap justify-between gap-3"><h3 class="serif text-2xl">2. Give knowledge promotion one atomic persistence operation</h3><div class="flex gap-2"><span class="rounded-full bg-teal-100 text-teal-900 px-3 py-1 text-sm font-bold">Implemented</span><span class="rounded-full bg-slate-800 text-white px-3 py-1 text-sm font-bold">P1</span></div></div>
117
+ <p class="evidence mt-4 text-slate-600">Evidence: the previous implementation issued two writes per proposal. `PhDB.promoteMemories()` now delegates to the memory repository (`src/db/index.ts:473`); the shared provenance and promotion use case is `src/knowledge/promotion.ts`, used by CLI (`src/commands/close.ts:101`) and MCP (`src/mcp/tools/projects.ts:8,21`). A rollback test covers the transaction in `src/db/__tests__/phdb.test.ts`.</p>
118
+ <h4 class="mt-5 font-bold">Problem</h4><p class="text-slate-700">Before this review, staged approval did not guarantee atomic persistence. A failed summary update or later proposal could leave a partial result. The fix now places the approved batch in one SQLite transaction; this candidate is addressed in the current working tree.</p>
119
+ <h4 class="mt-5 font-bold">Solution</h4><p class="text-slate-700">The shared promotion operation accepts the approved proposal batch and writes memories plus aggregate summaries atomically. CLI and MCP use the same operation. Provider generation and interactive review stay outside the transaction; the Seam is the approved proposal batch.</p>
120
+ <div class="grid sm:grid-cols-2 gap-3 mt-5"><div class="module-box border-rose-300"><b>Before</b><div class="mt-3 flex items-center gap-2 text-xs"><span>insert memory</span><span class="diagram-arrow">→</span><span>update summary</span><span class="diagram-arrow">→</span><span>repeat</span></div><p class="mt-2 text-xs text-rose-800">Failure can leave partial state.</p></div><div class="module-box border-teal-700"><b>After</b><div class="mt-3 rounded-lg bg-teal-50 p-3 text-xs">Approved batch <span class="diagram-arrow">→</span> single DB transaction <span class="diagram-arrow">→</span> consistent memories + summaries</div></div></div>
121
+ <div class="seam-line mt-8"></div><p class="mt-4 text-sm text-slate-700"><b>Seam:</b> transport-independent promotion input. <b>Deep Module:</b> persistence owns consistency and exposes one operation with a simple result.</p>
122
+ <table class="impact w-full mt-4 text-sm"><tr><th>Leverage</th><th>Locality</th><th>Tests</th></tr><tr><td>Both CLI and MCP get the same all-or-nothing guarantee.</td><td>Memory and summary consistency live beside database writes.</td><td>Inject a failure midway and assert neither side changed.</td></tr></table>
123
+ </article>
124
+
125
+ <article class="mt-6 rounded-2xl border border-amber-200 bg-white p-6 sm:p-8">
126
+ <div class="flex flex-wrap justify-between gap-3"><h3 class="serif text-2xl">3. Thin the MCP composition root and share cross-transport work</h3><div class="flex gap-2"><span class="rounded-full bg-teal-100 text-teal-900 px-3 py-1 text-sm font-bold">Implemented; handlers remain adapters</span><span class="rounded-full bg-slate-800 text-white px-3 py-1 text-sm font-bold">P1</span></div></div>
127
+ <p class="evidence mt-4 text-slate-600">Evidence: `src/mcp/server.ts` is now 50 lines. Tool definitions live in `src/mcp/tools/definitions.ts`; prompt, project, and timeline handlers are grouped in `src/mcp/tools/`; formatting is isolated in `format.ts`. `src/knowledge/{task-context,promotion}.ts` centralize shared retrieval and persistence.</p>
128
+ <h4 class="mt-5 font-bold">Problem</h4><p class="text-slate-700">The original server mixed protocol registration, all handlers, retrieval policy, writes, and formatting. The composition root is now small and tool code is local by domain. Some MCP-only search, timeline, and output behavior remains in adapter modules, so the transport boundary is improved but not fully domain-neutral.</p>
129
+ <h4 class="mt-5 font-bold">Solution</h4><p class="text-slate-700">The composition root now owns MCP SDK registration, handler dispatch, and error envelopes. Shared task-context retrieval and memory promotion live under `src/knowledge/` and are called by CLI and MCP. Tool-specific protocols and renderers remain grouped under `src/mcp/tools/`; further extraction should wait for another consumer.</p>
130
+ <div class="grid sm:grid-cols-2 gap-3 mt-5"><div class="module-box border-rose-300"><b>Before</b><div class="mt-3 text-xs space-y-2"><div class="rounded bg-rose-50 p-2">MCP root owns tool declarations, queries, fallback, and formatting</div><div class="rounded bg-rose-50 p-2">MCP root validates sources and performs persistence</div></div></div><div class="module-box border-teal-700"><b>After</b><div class="mt-3 text-xs space-y-2"><div class="rounded bg-teal-50 p-2">MCP root → grouped tool handlers → shared task-context use case</div><div class="rounded bg-teal-50 p-2">CLI / MCP → shared promotion use case → PhDB facade</div></div></div></div>
131
+ <div class="seam-line mt-8"></div><p class="mt-4 text-sm text-slate-700"><b>Seam:</b> transport-neutral application operations. <b>Deep Module:</b> reusable project knowledge behavior with a compact input/output contract.</p>
132
+ <table class="impact w-full mt-4 text-sm"><tr><th>Leverage</th><th>Locality</th><th>Tests</th></tr><tr><td>New transports reuse product behavior instead of cloning it.</td><td>Protocol concerns stop interleaving with retrieval and writes.</td><td>Use-case tests avoid MCP protocol setup; adapter tests focus on schemas and errors.</td></tr></table>
133
+ </article>
134
+
135
+ <article class="mt-6 rounded-2xl border border-amber-200 bg-white p-6 sm:p-8">
136
+ <div class="flex flex-wrap justify-between gap-3"><h3 class="serif text-2xl">4. Split cohesive persistence behind the PhDB facade</h3><div class="flex gap-2"><span class="rounded-full bg-teal-100 text-teal-900 px-3 py-1 text-sm font-bold">Implemented for memory and archive</span><span class="rounded-full bg-slate-800 text-white px-3 py-1 text-sm font-bold">P2</span></div></div>
137
+ <p class="evidence mt-4 text-slate-600">Evidence: `src/db/index.ts` is now a 521-line public facade with prompt CRUD, FTS, migrations, and query forwarding. Memory and summary persistence moved to `src/db/memory-repository.ts`; archive persistence moved to `src/db/archive-repository.ts`; vectors remain in `src/db/semantic-index.ts`.</p>
138
+ <h4 class="mt-5 font-bold">Problem</h4><p class="text-slate-700">PhDB previously owned SQL for prompt CRUD, FTS, archives, memories, and summaries in one implementation. Memory and archive SQL now live in cohesive repositories over the same connection. The facade deliberately retains source compatibility; prompt CRUD and FTS remain one group.</p>
139
+ <h4 class="mt-5 font-bold">Solution</h4><p class="text-slate-700">The extraction keeps prompt CRUD/FTS in the facade and moves memory/summary and archive SQL behind internal repositories. All repositories share one SQLite connection; `PhDB` method names and return values stay stable. Avoid widening the repository abstraction until a second adapter needs it.</p>
140
+ <div class="grid sm:grid-cols-2 gap-3 mt-5"><div class="module-box border-rose-300"><b>Before</b><div class="mt-3 flex flex-wrap gap-2 text-xs"><span class="bg-rose-50 rounded p-2">PhDB: prompt</span><span class="bg-rose-50 rounded p-2">memory</span><span class="bg-rose-50 rounded p-2">summary</span><span class="bg-rose-50 rounded p-2">archive</span><span class="bg-rose-50 rounded p-2">migrations</span></div></div><div class="module-box border-teal-700"><b>After</b><div class="mt-3 flex items-center gap-2 text-xs"><span class="bg-teal-50 rounded p-2">PhDB prompt facade</span><span class="diagram-arrow">→</span><span class="border-2 border-dashed border-teal-700 rounded p-2">MemoryRepository<br>ArchiveRepository</span><span class="diagram-arrow">→</span><span class="bg-teal-50 rounded p-2">shared SQLite</span></div></div></div>
141
+ <div class="seam-line mt-8"></div><p class="mt-4 text-sm text-slate-700"><b>Seam:</b> existing PhDB-to-SQLite boundary, narrowed around use cases. <b>Deep Module:</b> a repository operation that hides SQL and guarantees its domain invariant.</p>
142
+ <table class="impact w-full mt-4 text-sm"><tr><th>Leverage</th><th>Locality</th><th>Tests</th></tr><tr><td>Changes to archive or memory behavior affect fewer consumers.</td><td>Each persistence concern owns its schema/query details.</td><td>Test repository invariants against temporary SQLite; use-case tests use a small contract.</td></tr></table>
143
+ </article>
144
+ </section>
145
+
146
+ <section class="py-12 border-b border-slate-300">
147
+ <h2 class="serif text-3xl">Top Recommendation</h2>
148
+ <div class="mt-5 rounded-2xl bg-slate-900 text-white p-6 sm:p-8">
149
+ <p class="text-teal-200 text-sm uppercase tracking-widest font-bold">First move · validate the operational workflow</p>
150
+ <h3 class="serif text-3xl mt-3">Do not add another memory feature yet</h3>
151
+ <p class="mt-4 max-w-4xl text-slate-200">Three structural actions are now in place: a product-scope gate, transport-neutral task-context and promotion operations with grouped MCP modules, and internal memory/archive repositories behind the unchanged PhDB API. Keep `prepare` as a read-only experiment. The remaining product test is three real tasks on different projects; record whether the brief prevented repeated work before adding more features.</p>
152
+ <p class="mt-4 max-w-4xl text-slate-200">Why this comes first: the biggest risk is not that PH lacks another abstraction. It is that summaries, memories, and tool-specific retrieval behavior drift while product value remains unmeasured. A transaction seam protects data now; a usage gate protects the project from building maintenance around an unproven loop.</p>
153
+ </div>
154
+ </section>
155
+
156
+ <section class="py-12 border-b border-slate-300">
157
+ <h2 class="serif text-3xl">Usage Modes</h2>
158
+ <div class="grid md:grid-cols-2 gap-4 mt-6">
159
+ <div class="module-box"><h3 class="font-bold">Capture and import history</h3><p class="mt-2 text-sm text-slate-600">Direct logging, wrappers, hooks, and importers normalize into prompt records.</p><p class="evidence mt-3">`src/capture/index.ts`, `src/importer/`, `src/commands/log.ts`, `hooks/`</p></div>
160
+ <div class="module-box"><h3 class="font-bold">Search local prompt history</h3><p class="mt-2 text-sm text-slate-600">SQLite FTS supports text search; sqlite-vec adds optional semantic search.</p><p class="evidence mt-3">`src/commands/search.ts`, `src/db/index.ts:246-345`, `src/db/semantic-index.ts`</p></div>
161
+ <div class="module-box"><h3 class="font-bold">Browse and curate records</h3><p class="mt-2 text-sm text-slate-600">The Ink interface filters, previews, edits metadata, exports, and reruns prompts.</p><p class="evidence mt-3">`src/ui/BrowseApp.tsx`, `src/ui/FilterPanel.tsx`, `src/ui/PreviewPane.tsx`</p></div>
162
+ <div class="module-box"><h3 class="font-bold">Expose history and project context to agents</h3><p class="mt-2 text-sm text-slate-600">MCP serves prompt queries and project knowledge; project tools call shared task-context retrieval and promotion use cases.</p><p class="evidence mt-3">`src/mcp/server.ts`, `src/mcp/tools/`, `src/knowledge/`</p></div>
163
+ <div class="module-box"><h3 class="font-bold">Prepare and promote operational knowledge</h3><p class="mt-2 text-sm text-slate-600">`prepare` retrieves a bounded brief; `close` proposes curated memory after provider analysis and user approval. Implemented in the current dirty tree; three-project real-use validation remains outstanding.</p><p class="evidence mt-3">`src/commands/prepare.ts`, `src/commands/close.ts`, `docs/specs/SPEC-016-operational-memory.md`</p></div>
164
+ <div class="module-box"><h3 class="font-bold">Synchronize with a remote PH server</h3><p class="mt-2 text-sm text-slate-600">An optional HTTP service supports prompt push/pull and memory lookups. It adds a second deployment and security surface.</p><p class="evidence mt-3">`src/server/index.ts`, `src/commands/remote.ts`</p></div>
165
+ </div>
166
+ <div class="mt-8 grid md:grid-cols-2 gap-4">
167
+ <div class="rounded-xl bg-teal-50 border border-teal-300 p-5"><h3 class="font-bold text-teal-950">Ready for...</h3><p class="mt-2 text-sm text-slate-700">Local prompt capture, search, browsing, and opt-in agent access to a user's own project history. The operational-memory commands are implemented and pass their current automated suite.</p></div>
168
+ <div class="rounded-xl bg-rose-50 border border-rose-300 p-5"><h3 class="font-bold text-rose-950">Still requires integration...</h3><p class="mt-2 text-sm text-slate-700">Evidence that the prepare/close loop improves real tasks; retrieval evaluation against the configured embedding model; and a coherent support boundary for the many transports and commands.</p></div>
169
+ </div>
170
+ </section>
171
+
172
+ <footer class="pt-8 text-sm text-slate-600 flex flex-wrap justify-between gap-3">
173
+ <span>PH Architecture Review · Based on the working tree at review time</span>
174
+ <span>Created: 2026-10-22 · Updated: 2026-10-22</span>
175
+ </footer>
176
+ </main>
177
+ <script>mermaid.initialize({startOnLoad:true,theme:'neutral',securityLevel:'strict'});</script>
178
+ </body>
179
+ </html>
package/docs/ph-manual.md CHANGED
@@ -1,14 +1,14 @@
1
1
  # ph — Prompt History and Project Memory
2
2
 
3
- **Zero-friction capture, semantic search, project memory, and MCP-based knowledge retrieval for AI CLI tools.**
3
+ **Capture AI CLI work, find it later, and retrieve project context when you need it.**
4
4
 
5
5
  ---
6
6
 
7
7
  ## 1. Overview
8
8
 
9
- ph is a transparent observability and knowledge layer for AI CLI tools (Claude Code, Codex CLI, Gemini CLI, OpenCode, etc.). It automatically records every prompt+response into a local SQLite database with full-text search, semantic vector search, LLM-based analysis, Git context snapshots, session grouping, and an interactive TUI browser.
9
+ ph is a local history and project-context tool for AI CLI work. It records interactions through native hooks or by wrapping a tool, then helps you search history and retrieve project context from the terminal.
10
10
 
11
- **Core principle:** ph captures conversations without changing the normal tool workflow. Optional analysis turns captured history into project summaries and memories that can be searched locally or requested by an MCP client. Capture and full-text search work without an LLM provider; analysis, embeddings, and semantic search require the configured provider.
11
+ **Core principle:** ph captures conversations without changing the normal tool workflow. Optional analysis enriches each captured interaction with searchable summary, insights, decisions, and classification. Analysis does not promote active project memories; `ph close` and MCP `save_decision` are the explicit promotion paths. Capture and full-text search work without an LLM provider; analysis, embeddings, and semantic search require the configured provider.
12
12
 
13
13
  ### Key Features
14
14
 
@@ -17,7 +17,7 @@ ph is a transparent observability and knowledge layer for AI CLI tools (Claude C
17
17
  - **LLM analysis** — role/tag/relevance classification, summary extraction, key insights, technical decisions
18
18
  - **Project memory** — per-project accumulated knowledge with deduped insights and decisions
19
19
  - **MCP server** — tools for agents to search memories, check project knowledge, get context
20
- - **Interactive TUI** — browse, filter, edit, star, re-run, export prompts
20
+ - **Plain-text CLI** — the everyday interface is a small set of terminal commands
21
21
  - **Session grouping** — automatic conversation grouping with cohesion scoring
22
22
  - **Git context** — records branch, modified files, and diff at capture time
23
23
  - **Background analysis** — async LLM processing after each capture (optional)
@@ -45,7 +45,7 @@ npm link
45
45
 
46
46
  ```bash
47
47
  ph config set background-analysis true # auto-analyze after each capture
48
- ph config set analyze-provider ollama # ollama (default) or gemini
48
+ ph config set analyze-provider ollama # ollama (default), gemini, openrouter, or mlx-serve
49
49
  ph config set ollama-model llama3.1:latest
50
50
  ```
51
51
 
@@ -98,18 +98,41 @@ echo '{"tool":"claude","prompt":"hi","response":"hello"}' | ph log --stdin
98
98
 
99
99
  ---
100
100
 
101
- ## 4. CLI Commands
101
+ ## 4. Everyday Commands
102
102
 
103
103
  | Command | Description |
104
104
  |---------|-------------|
105
- | `ph` (no args) | Open interactive TUI browser |
105
+ | `ph` | Print the short usage guide |
106
+ | `ph setup` | Connect installed Claude Code, Codex CLI, Gemini CLI, and OpenCode for automatic capture |
107
+ | `ph <tool> [args...]` | Run an AI CLI tool and capture the interaction |
108
+ | `ph search <query>` | Find earlier work in the current project (five matches by default) |
109
+ | `ph show <id>` | Inspect the complete prompt, response, capture metadata, and analysis |
110
+ | `ph show <id> --json` | Print the complete interaction as JSON |
111
+ | `ph context "task"` | Retrieve project knowledge and related prompts |
112
+ | `ph close` | Review the last three hours and approve useful project knowledge |
113
+
114
+ `ph setup` is the recommended first step for everyday use. It detects installed supported tools (Claude Code, Codex CLI, Gemini CLI, and OpenCode), installs their native capture integrations, preserves existing settings, and reports whether each integration was installed or already configured. Pass tool names to choose explicitly. After setup, keep using your AI CLI normally; `ph search "query"` is the main command for retrieving earlier work. `ph <tool>` remains as a wrapper alternative.
115
+
116
+ `ph search "query"` searches the project detected from the current directory and returns five matches by default, ordered by text relevance. Use `--limit <n>` to show more, or `--all` to search across every project. When no project can be detected, PH searches all saved work and labels that scope. Searches with no current-project matches explain how to broaden the search.
117
+
118
+ `ph prepare "task"` remains as a compatibility alias for task-aware `ph context`.
119
+ `ph browse` is a compatibility alias for a plain-text list of recent interactions.
120
+ Use `ph help --all` for maintenance and integration commands, including `ph status` for recent capture and background-work state.
121
+
122
+ ## 4a. Advanced Command Reference
123
+
124
+ | Command | Description |
125
+ |---------|-------------|
126
+ | `ph` (no args) | Print the short everyday-use guide |
106
127
  | `ph <tool> [args...]` | Wrapper mode — run tool + capture |
107
- | `ph search [query]` | Full-text search prompts |
128
+ | `ph search [query]` | Full-text search (current project, five matches by default) |
108
129
  | `ph search --semantic <query>` | Semantic (vector) search |
109
130
  | `ph search --archive` | Search archived prompts |
110
- | `ph search -i <query>` | Open results in interactive TUI |
111
131
  | `ph last [n]` | Show last N prompts |
112
- | `ph context [query]` | Get RAG context for current project |
132
+ | `ph context [task]` | Retrieve task-aware project context; works without semantic embeddings |
133
+ | `ph prepare "<task>"` | Compatibility alias for task-aware context retrieval |
134
+ | `ph browse` | Compatibility alias for recent text results |
135
+ | `ph close [--since 3h]` | Review recent work and propose knowledge for explicit approval |
113
136
  | `ph sessions` | Group prompts into work sessions |
114
137
  | `ph timeline <project>` | Full chronological project history |
115
138
  | `ph stats` | History statistics |
@@ -120,10 +143,11 @@ echo '{"tool":"claude","prompt":"hi","response":"hello"}' | ph log --stdin
120
143
  | `ph cleanup --retention` | Archive old/unqualified prompts per retention policy |
121
144
  | `ph cleanup-reusability` | Cleanup by reusability score |
122
145
  | `ph star <id>` | Toggle bookmark |
123
- | `ph export <id>` | Export prompt (txt/json/md) |
146
+ | `ph export <id> [--format txt|json|md] [--archive]` | Export a complete interaction |
147
+ | `ph status` | Show recent capture, analysis, and remote-push state without content |
124
148
  | `ph import gemini|claude|opencode|codex` | Import from AI CLI history |
125
149
  | `ph log --tool <name> ...` | Direct log (hook target) |
126
- | `ph embed-all` | Generate embeddings for all prompts |
150
+ | `ph embed-all` | Generate embeddings for prompts without vectors |
127
151
  | `ph config get|set <key> <value>` | View/edit config |
128
152
  | `ph vacuum` | Compact SQLite database |
129
153
  | `ph memory-migrate` | Merge existing memories into project_summaries |
@@ -136,7 +160,6 @@ echo '{"tool":"claude","prompt":"hi","response":"hello"}' | ph log --stdin
136
160
  ### Search options
137
161
 
138
162
  ```
139
- -i / --interactive Open in TUI browser
140
163
  --tool <name> Filter by tool
141
164
  --project <name> Filter by project
142
165
  --language <lang> Filter by language
@@ -147,11 +170,12 @@ echo '{"tool":"claude","prompt":"hi","response":"hello"}' | ph log --stdin
147
170
  --archive Search archived prompts
148
171
  --since YYYY-MM-DD Start date
149
172
  --until YYYY-MM-DD End date
150
- --limit <n> Max results (default 50)
173
+ --limit <n> Max results (default 5)
174
+ --all Search across all projects instead of the current project
151
175
  --top Quality >= 8
152
176
  --min-quality <n> Min quality (0-10)
153
177
  --min-relevance <n> Min relevance (0-10)
154
- --full Show full prompt text
178
+ --full Show full prompt and response text
155
179
  ```
156
180
 
157
181
  ### Context options
@@ -183,43 +207,13 @@ echo '{"tool":"claude","prompt":"hi","response":"hello"}' | ph log --stdin
183
207
 
184
208
  ---
185
209
 
186
- ## 5. TUI Keybindings
187
-
188
- | Key | Action |
189
- |-----|--------|
190
- | `Up` / `Down`, `Page Up` / `Page Down` | Navigate list |
191
- | `Tab` | Switch pane (wide mode) |
192
- | `1`, `2`, `3` | Switch prompt/response/memory tab |
193
- | `y` | Copy to clipboard |
194
- | `s` | Toggle star |
195
- | `e` | Edit metadata |
196
- | `r` | Rerun prompt (edit before launch) |
197
- | `Shift+C` | Chat mode: launch tool with project context |
198
- | `x` | Delete entry |
199
- | `/` | Search |
200
- | `o` | Settings panel (toggle auto-analysis, view config) |
201
- | `f` | Filter panel (flat list, Enter toggle, letter jump) |
202
- | `c` | Clear all filters |
203
- | `q` / `Escape` | Quit / back |
204
-
205
- ### TUI components
206
-
207
- - **SearchBar** — always visible spotlight bar at top
208
- - **FilterPanel** — flat scrollable list of filter options with counts `[N]`, toggle with Enter, jump by letter
209
- - **SettingsView** — config viewer/editor (auto-analysis toggle, ollama URL/model, filters)
210
- - **PreviewPane** — three tabs (prompt/response/memory). Memory tab shows project-level knowledge
211
- - **ListEntry** — role marker, analysis status, star, Q/R badges, optional summary line
212
- - **Footer** — context-sensitive hints (shows `C:chat` only when entry has project)
213
-
214
- ---
215
-
216
- ## 6. Project Memory System
210
+ ## 5. Project Memory System
217
211
 
218
212
  ph maintains two levels of per-project knowledge:
219
213
 
220
- ### 6a. `project_summaries` (curated, 1 row per project)
214
+ ### 5a. `project_summaries` (curated, 1 row per project)
221
215
 
222
- Accumulated knowledge with deduped insights and decisions. Updated on every analysis. Primary source for MCP tools.
216
+ Accumulated, explicitly promoted knowledge with deduped insights and decisions. Updated by approved `close` proposals, MCP `save_decision`, and legacy migration; automatic analysis does not write here.
223
217
 
224
218
  ```bash
225
219
  # View accumulated project knowledge
@@ -229,9 +223,29 @@ ph context --project myproject
229
223
  # get_project_summary(project: "myproject")
230
224
  ```
231
225
 
232
- ### 6b. `memories` (append-only timeline)
226
+ ### 5b. `memories` (append-only timeline)
227
+
228
+ Legacy append-only project knowledge records retained for detailed audit. New automatic analysis results stay on their source interaction instead of creating memory rows.
229
+
230
+ ### Operational workflow: retrieve, work, review
231
+
232
+ ```bash
233
+ # Read-only task context; project auto-detected from the current directory
234
+ ph context "add Wise provider" --limit 5 --budget 3500
235
+
236
+ # Inspect the selection without calling an LLM
237
+ ph close --dry-run --since 3h
238
+
239
+ # Generate knowledge proposals; approve, edit, skip, or quit each one
240
+ ph close --since 3h
241
+ ph close --from 1670 --to 1682 --project ph
242
+ ```
243
+
244
+ `context` uses the task as a semantic retrieval query and prints source-linked prompt and memory excerpts. If Ollama embeddings are unavailable, it labels the fallback to recent project context. Retrieval never writes to SQLite. `prepare` remains an alias for compatibility. The character budget limits retrieved content; when the source list itself is larger than the budget, source IDs take precedence and the output can exceed the requested budget.
233
245
 
234
- Full chronological history of every analysis run. Preserved for detailed audit.
246
+ `close` selects prompt/response pairs within one project, displays them before generation, and asks the configured analysis provider for durable proposals. It checks for a terminal before making that provider call. Each accepted proposal creates an append-only memory tied to its source prompt IDs; the approved batch and summary updates are committed in one SQLite transaction. A persistence failure rolls back the whole batch. Provider errors, malformed output, dry-run, skipping, and quitting do not promote unapproved knowledge.
247
+
248
+ MCP `check_project_knowledge` uses the same retrieval and rendering boundary. MCP `save_decision` accepts optional `promptIds` and rejects missing or cross-project sources.
235
249
 
236
250
  ### Memory migration
237
251
 
@@ -243,7 +257,7 @@ ph memory-migrate # one-time: merge all memories into project_summaries
243
257
 
244
258
  ---
245
259
 
246
- ## 7. Retention & Archiving
260
+ ## 6. Retention & Archiving
247
261
 
248
262
  Configurable auto-archiving to keep the database lean:
249
263
 
@@ -266,9 +280,9 @@ ph search --archive
266
280
 
267
281
  ---
268
282
 
269
- ## 8. Background Analysis
283
+ ## 7. Background Analysis
270
284
 
271
- When enabled, every `ph log` automatically spawns a detached child process that analyzes the new entry (role, tags, relevance, summary, key insights, technical decisions).
285
+ When enabled, every `ph log` marks analysis pending and starts a detached child process that adds role, tags, relevance, summary, key insights, and technical decisions to the interaction. It does not create project memories or summaries. `ph status` shows pending, complete, or safe failure state. Remote push status is shown when configured.
272
286
 
273
287
  ```bash
274
288
  ph config set background-analysis true
@@ -283,9 +297,40 @@ ph config set ollama-model llama3.1:latest
283
297
  ph config set ollama-embed-model nomic-embed-text-v2-moe
284
298
  ```
285
299
 
300
+ OpenRouter and MLX-Serve generation use `@gi4nks/wise`:
301
+
302
+ ```bash
303
+ # OpenRouter: credentials stay in the environment; model IDs keep provider/model.
304
+ export OPENROUTER_API_KEY="your_openrouter_api_key"
305
+ ph models openrouter
306
+ ph config set openrouter-api-key # hidden prompt; or keep using the environment
307
+ ph config set analyze-provider openrouter
308
+ ph config set openrouter-model "provider/model-id"
309
+ ph config show # provider settings with credentials redacted
310
+ ph analyze
311
+
312
+ # MLX-Serve on Parmenide: open this tunnel in a separate terminal.
313
+ ssh -N -L 11234:127.0.0.1:11234 parmenide
314
+ ```
315
+
316
+ ```bash
317
+ # In the terminal where you run ph:
318
+ ph models mlx-serve
319
+ ph config set analyze-provider mlx-serve
320
+ ph config set mlx-serve-model "exact-model-id-from-server"
321
+ ph analyze
322
+ ```
323
+
324
+ MLX-Serve defaults to `http://127.0.0.1:11234/v1`. Override it with
325
+ `MLX_SERVE_BASE_URL` or `ph config set mlx-serve-url <url>`. Set
326
+ `MLX_SERVE_API_KEY` if the server requires auth; `GLB_OMLX_API_KEY` is also
327
+ accepted for existing setups. Alternatively run `ph config set mlx-serve-api-key`
328
+ to enter it without echoing it in the terminal. `ph config show` redacts
329
+ credentials. `ph models mlx-serve` marks entries `[loaded]` or `[unloaded]`.
330
+
286
331
  ---
287
332
 
288
- ## 9. MCP Server
333
+ ## 8. MCP Server
289
334
 
290
335
  ph exposes an MCP (Model Context Protocol) server over stdio for AI agents:
291
336
 
@@ -311,26 +356,30 @@ ph mcp
311
356
 
312
357
  ---
313
358
 
314
- ## 10. HTTP Server & Remote Sync
359
+ ## 9. HTTP Server & Remote Sync
315
360
 
316
361
  Share prompt history across machines:
317
362
 
318
363
  ```bash
319
- # Start server
320
- ph server --port 3001 --host 0.0.0.0
321
-
322
- # From another machine
364
+ # Configure the required server key, then start on loopback
365
+ ph config set remote-api-key "$PH_REMOTE_API_KEY"
366
+ ph server --port 3001
367
+
368
+ # On the server, expose the listener only on a protected interface and put TLS
369
+ # in front of it before using the endpoint across an untrusted network.
370
+ # On each client, set the server URL and the same key:
371
+ ph config set remote-api-key "$PH_REMOTE_API_KEY"
323
372
  ph config set remote-url http://server-ip:3001
324
- ph remote push # send local unsynced prompts
325
- ph remote pull # fetch remote prompts
373
+ ph remote push # resumable ID-based sync
374
+ ph remote pull # resumable ID-based sync
326
375
  ph remote status # show sync state
327
376
  ```
328
377
 
329
- Every `ph log` auto-pushes to remote if configured (fire-and-forget, never blocks).
378
+ The server requires a key before it starts, binds to `127.0.0.1` by default, and exposes only a status value at public `/health`. All data routes require Bearer authentication. Push and pull cursors are scoped to the remote target and the local database UUID. Push pages are split to stay below the 32 MiB request-body limit; interrupted pages can be retried safely. Bulk push waits at a live wrapper record and continues after the response is saved. `ph log` and both wrapper modes push after capture; requests time out after five seconds so an unavailable server cannot hang the command indefinitely. An invalid optional remote URL marks sync failed while the interaction remains saved locally and the wrapped CLI still runs. Current limitation: replacing the remote database behind the same URL is not detected, and last-push/pull status times are global across targets.
330
379
 
331
380
  ---
332
381
 
333
- ## 11. Database
382
+ ## 10. Database
334
383
 
335
384
  **Location:** `~/.prompt_history.db` (configurable via `ph config set db-path`)
336
385
 
@@ -351,12 +400,12 @@ Every `ph log` auto-pushes to remote if configured (fire-and-forget, never block
351
400
  ph vacuum # compact DB
352
401
  ph cleanup # remove short/trivial/duplicate prompts
353
402
  ph cleanup --retention # archive per retention policy
354
- ph embed-all # (re)generate all embeddings
403
+ ph embed-all # generate vectors for prompts without embeddings
355
404
  ```
356
405
 
357
406
  ---
358
407
 
359
- ## 12. Filter Pipeline
408
+ ## 11. Filter Pipeline
360
409
 
361
410
  Before saving, ph filters out:
362
411
 
@@ -375,16 +424,20 @@ ph config set filter-min-relevance 3
375
424
 
376
425
  ---
377
426
 
378
- ## 13. Configuration (`~/.ph_config.json`)
427
+ ## 12. Configuration (`~/.ph_config.json`)
379
428
 
380
429
  | Key | Default | Description |
381
430
  |-----|---------|-------------|
382
431
  | `dbPath` | `~/.prompt_history.db` | SQLite database path |
383
- | `analyzeProvider` | `ollama` | LLM provider: `ollama` or `gemini` |
432
+ | `analyzeProvider` | `ollama` | LLM provider: `ollama`, `gemini`, `openrouter`, or `mlx-serve` |
384
433
  | `ollamaUrl` | `http://localhost:11434` | Ollama server URL |
385
434
  | `ollamaModel` | `llama3.1:latest` | Analysis model |
386
435
  | `ollamaEmbedModel` | `nomic-embed-text-v2-moe` | Embedding model |
387
436
  | `geminiApiKey` | — | Gemini API key |
437
+ | `openrouterModel` | — | Exact OpenRouter model ID |
438
+ | `openrouterUrl` | `https://openrouter.ai/api/v1` | OpenRouter-compatible API root |
439
+ | `mlxServeModel` | — | Exact MLX-Serve model ID |
440
+ | `mlxServeUrl` | `http://127.0.0.1:11234/v1` | MLX-Serve API root (Parmenide SSH tunnel by default) |
388
441
  | `backgroundAnalysis` | `false` | Auto-analyze after each capture |
389
442
  | `filterMinLength` | `15` | Min prompt length to keep |
390
443
  | `filterMinRelevance` | `3` | Min relevance to keep (0=disable) |
@@ -394,12 +447,16 @@ ph config set filter-min-relevance 3
394
447
  | `retentionMinRelevance` | `3` | Archive prompts below this relevance |
395
448
  | `remoteUrl` | — | Remote ph server URL (or `PH_REMOTE_URL` env) |
396
449
  | `remoteApiKey` | — | Remote server API key |
397
- | `remoteLastPush` | — | Timestamp of last successful push |
398
- | `remoteLastPull` | — | Timestamp of last successful pull |
450
+ | `remoteLastPush` | — | Global timestamp of last successful push |
451
+ | `remoteLastPull` | — | Global timestamp of last successful pull |
452
+
453
+ Provider API credentials are environment-only: `OPENROUTER_API_KEY` and
454
+ `MLX_SERVE_API_KEY` (`GLB_OMLX_API_KEY` is a fallback). They are not written to
455
+ `~/.ph_config.json`.
399
456
 
400
457
  ---
401
458
 
402
- ## 14. Architecture
459
+ ## 13. Architecture
403
460
 
404
461
  ```
405
462
  Hook/Import → ph log → prompts table (FTS5 indexed)
@@ -432,14 +489,13 @@ src/
432
489
  filter/ # Capture-time filter pipeline
433
490
  mcp/server.ts # MCP stdio server
434
491
  server/index.ts # HTTP REST server (zero deps)
435
- ui/ # React/Ink TUI, including extracted filter policy and panel
436
492
  importer/ # Gemini/Claude/OpenCode/Codex history importers
437
493
  hooks/ # Shell scripts and plugins for AI tools
438
494
  ```
439
495
 
440
496
  ---
441
497
 
442
- ## 15. Importing Existing History
498
+ ## 14. Importing Existing History
443
499
 
444
500
  ```bash
445
501
  # Import from Claude Code
@@ -463,7 +519,7 @@ ph import codex
463
519
 
464
520
  ---
465
521
 
466
- ## 16. Versioning and Releases
522
+ ## 15. Versioning and Releases
467
523
 
468
524
  Use Conventional Commits to describe changes: `feat:` requests a minor release,
469
525
  `fix:` requests a patch release, and `BREAKING CHANGE:` requests a major release.