@gi4nks/ph 1.7.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.
@@ -0,0 +1,104 @@
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="color-scheme" content="light dark">
7
+ <title>ph — From Prompt History to Operational Memory</title>
8
+ <style>
9
+ :root{font-family:Inter,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;color:#172033;background:#f4f6fa;font-synthesis:none;text-rendering:optimizeLegibility;--ink:#172033;--muted:#64748b;--line:#dbe2ec;--accent:#0969da;--soft:#eaf2ff;--good:#087443;--warn:#995c00;--card:#fff}
10
+ *{box-sizing:border-box}body{margin:0;line-height:1.58}main{max-width:1040px;margin:0 auto;padding:48px 28px 72px}header{padding:34px 38px;border-radius:20px;background:linear-gradient(135deg,#102a43,#174e7a);color:white}header p{max-width:720px;color:#d6e7f5}h1{font-size:clamp(2rem,5vw,3.3rem);line-height:1.08;letter-spacing:-.04em;margin:.2em 0}h2{margin:44px 0 12px;font-size:1.55rem;letter-spacing:-.025em}h3{margin:0 0 7px;font-size:1.05rem}p{margin:8px 0 14px}.eyebrow{text-transform:uppercase;letter-spacing:.14em;font-size:.75rem;font-weight:750;color:#a8d5ff}.meta{display:flex;gap:18px;flex-wrap:wrap;font-size:.9rem;color:#d6e7f5}.callout{background:var(--soft);border-left:4px solid var(--accent);padding:17px 20px;border-radius:0 12px 12px 0;margin:22px 0}.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:14px}.card{background:var(--card);border:1px solid var(--line);border-radius:14px;padding:18px}.card p{font-size:.94rem;color:var(--muted);margin-bottom:0}.tag{display:inline-block;background:#edf2f7;color:#334155;border-radius:999px;padding:3px 9px;font-size:.77rem;font-weight:700}.tag.good{background:#e8f6ee;color:var(--good)}table{width:100%;border-collapse:collapse;background:var(--card);border:1px solid var(--line);border-radius:14px;overflow:hidden;font-size:.91rem}th,td{text-align:left;vertical-align:top;padding:13px 14px;border-bottom:1px solid var(--line)}th{background:#edf2f7;font-size:.82rem;text-transform:uppercase;letter-spacing:.06em}tr:last-child td{border-bottom:0}td:first-child{font-weight:700;min-width:150px}.decision{border:2px solid var(--accent);border-radius:16px;padding:22px;background:var(--card)}.decision strong{color:var(--accent)}ol,ul{padding-left:1.25rem}li{padding:3px 0}.flow{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin:18px 0}.step{padding:15px;border-radius:12px;background:var(--card);border:1px solid var(--line)}.step b{display:block;color:var(--accent);margin-bottom:5px}.small{font-size:.88rem;color:var(--muted)}code{background:#edf2f7;border-radius:5px;padding:2px 5px;font-size:.9em}footer{border-top:1px solid var(--line);margin-top:42px;padding-top:18px;color:var(--muted);font-size:.84rem}
11
+ @media(max-width:700px){main{padding:20px 14px 44px}header{padding:25px 22px}.flow{grid-template-columns:1fr 1fr}table{font-size:.82rem}th,td{padding:9px}}
12
+ @media(prefers-color-scheme:dark){:root{color:#e5edf7;background:#0c1421;--ink:#e5edf7;--muted:#a3b2c5;--line:#2c3b50;--soft:#132b45;--card:#121e2d}header{background:linear-gradient(135deg,#0c1c2b,#153d5d)}th{background:#1b2a3c}code,.tag{background:#253448;color:#d7e6f8}.tag.good{background:#123a2b;color:#86e0ae}}
13
+ </style>
14
+ </head>
15
+ <body>
16
+ <main>
17
+ <header>
18
+ <div class="eyebrow">Product analysis · October 10, 2026</div>
19
+ <h1>From Prompt History<br>to Operational Memory</h1>
20
+ <p>Product question: How can ph turn prompts, responses, and analysis into knowledge that helps with the next task handled by an AI agent?</p>
21
+ <div class="meta"><span>Scope: ph</span><span>Status: direction approved; Phases 0–3 implemented</span><span>Horizon: first incremental release</span></div>
22
+ </header>
23
+
24
+ <div class="callout"><strong>Thesis:</strong> ph creates value when it prevents context from being repeated, decisions from being rediscovered, and failed attempts from being repeated. Conversation analysis is a means; the outcome is reliable memory brought into the workflow at the right time.</div>
25
+
26
+ <h2>Starting Point</h2>
27
+ <div class="grid">
28
+ <article class="card"><span class="tag good">Available</span><h3>Work evidence</h3><p>Prompts and responses are captured with project, tool, and Git context. Memories can retain the IDs of their source prompts.</p></article>
29
+ <article class="card"><span class="tag good">Available</span><h3>Project knowledge</h3><p>Append-only memories, curated summaries, MCP decision saving, and shared retrieval through <code>ph context</code>, chat, and MCP tools.</p></article>
30
+ <article class="card"><span class="tag">Gap</span><h3>No guided workflow</h3><p>There is no explicit step to prepare a task with relevant prior work and no review step to turn its outcome into verifiable knowledge.</p></article>
31
+ </div>
32
+ <p class="small">The existing ph evolution plan already established curated memory, MCP, and noise reduction. This proposal makes the operational cycle explicit without replacing those foundations.</p>
33
+
34
+ <h2>Options Considered</h2>
35
+ <table>
36
+ <thead><tr><th>Option</th><th>Benefits</th><th>Costs and risks</th><th>Assessment</th></tr></thead>
37
+ <tbody>
38
+ <tr><td>A · Analytics dashboard</td><td>Makes volume, roles, models, and trends visible; useful for inspecting history.</td><td>Does not bring knowledge into the workflow. It may optimize metrics that do not reduce repeated work.</td><td><span class="tag">Not a priority</span></td></tr>
39
+ <tr><td>B · Automatic injection everywhere</td><td>Context is always available with little user effort.</td><td>Can add noise, tokens, latency, and stale context to every request. Its usefulness is difficult to establish.</td><td><span class="tag">Avoid as the default</span></td></tr>
40
+ <tr><td>C · Prepare → work → approve</td><td>Makes reuse intentional, preserves sources and consent, and uses existing context, memory, and MCP capabilities.</td><td>Requires a brief user action and a useful proposal summary. Manual promotion adds a step.</td><td><span class="tag good">Recommended</span></td></tr>
41
+ <tr><td>D · Autonomous memory agent</td><td>Could extract and update knowledge without interrupting the workflow.</td><td>Harder to control; silent corrections, duplicates, and unapproved decisions could contaminate memory.</td><td><span class="tag">Consider after testing C</span></td></tr>
42
+ </tbody>
43
+ </table>
44
+
45
+ <h2>Decision</h2>
46
+ <section class="decision">
47
+ <p><strong>Build a deliberate, measurable workflow and reuse the current data model in the first release.</strong></p>
48
+ <p>Memory becomes useful when a user or agent consults it before acting and can save what it learned with references to the conversations that support it. Do not introduce a new knowledge graph or always-on agent in the first release.</p>
49
+ <p class="small">Decision record: direction approved in conversation; implementation details are in <a href="plans/2026-10-10-operational-memory.md">the operational memory work plan</a>.</p>
50
+ </section>
51
+
52
+ <h2>Implementable Workflow</h2>
53
+ <div class="flow">
54
+ <div class="step"><b>1 · Prepare</b><code>ph prepare "task"</code><br><span class="small">Detect project, retrieve relevant context, identify sources.</span></div>
55
+ <div class="step"><b>2 · Work</b><span class="small">The user or agent completes the task with essential context.</span></div>
56
+ <div class="step"><b>3 · Review</b><code>ph close</code><br><span class="small">Propose decisions or procedures with supporting prompt IDs.</span></div>
57
+ <div class="step"><b>4 · Promote</b><span class="small">Approve before saving or updating project memory.</span></div>
58
+ </div>
59
+ <ul>
60
+ <li><strong>Prepare:</strong> Reuse <code>getProjectContext()</code> and semantic search. Produce a short brief with decisions, gotchas, prior work, and source IDs. State clearly when there is no evidence.</li>
61
+ <li><strong>Close:</strong> Start from recent prompts or an explicitly selected range/session. Propose zero or more decisions and procedures. Show what would be saved and which <code>prompt_ids</code> support it.</li>
62
+ <li><strong>Approval before promotion:</strong> Reuse the existing <code>save_decision</code> and project summary paths, extending them to preserve sources. No permanent update without approval.</li>
63
+ <li><strong>Lightweight feedback:</strong> Later, consider useful / irrelevant / stale feedback for retrieved memories. Existing access counters are not an explicit usefulness judgment.</li>
64
+ </ul>
65
+
66
+ <h2>Trade-offs and Guardrails</h2>
67
+ <table>
68
+ <thead><tr><th>Product decision</th><th>Choice</th><th>Reason</th></tr></thead>
69
+ <tbody>
70
+ <tr><td>When to retrieve</td><td>On request through <code>prepare</code> and agent paths explicitly chosen by the user</td><td>Reduces irrelevant additions and keeps the workflow predictable.</td></tr>
71
+ <tr><td>What to keep</td><td>Confirmed decisions and procedures linked to sources</td><td>Reduces duplicates and makes a memory auditable and correctable.</td></tr>
72
+ <tr><td>Evidence status</td><td>Distinguish verified, inferred, and unverified claims</td><td>A fluent summary is not proof that a procedure still works.</td></tr>
73
+ <tr><td>Cross-project retrieval</td><td>Out of scope for the first release</td><td>Information from one project may be false or sensitive in another.</td></tr>
74
+ </tbody>
75
+ </table>
76
+
77
+ <h2>Cost, Rate Limits, and Latency</h2>
78
+ <div class="grid">
79
+ <article class="card"><h3>Prepare</h3><p>Lexical search and database reads are local. Semantic retrieval may call an Ollama embedding endpoint; there is no cloud generation cost, while latency and availability depend on the server.</p></article>
80
+ <article class="card"><h3>Close</h3><p>Proposal extraction can use one optional LLM call. OpenRouter may incur cost and rate limits; MLX-Serve depends on the tunnel and loaded model. Make the provider explicit and let the user skip proposals.</p></article>
81
+ <article class="card"><h3>Brief limits</h3><p>Apply a configurable character or token budget, show source counts, and truncate raw prompts first. Do not make extra LLM calls whenever the TUI opens.</p></article>
82
+ </div>
83
+
84
+ <h2>How to Measure Success</h2>
85
+ <p>Measure useful reuse, not the volume of analysis:</p>
86
+ <ul>
87
+ <li><strong>Prepare relevance:</strong> the first retrieved memories are relevant to the task and project in judged cases.</li>
88
+ <li><strong>Reuse rate:</strong> the user confirms that prior work changed or accelerated the task.</li>
89
+ <li><strong>Source reliability:</strong> every proposed decision links to verifiable prompts and responses; no source is attributed incorrectly.</li>
90
+ <li><strong>Workflow friction:</strong> prepare and close take few steps and can be skipped.</li>
91
+ <li><strong>Real task evaluation:</strong> expand the retrieval set in <code>docs/evals/context-retrieval-golden.json</code> with work queries from multiple projects.</li>
92
+ </ul>
93
+
94
+ <h2>Usage Check · October 10, 2026</h2>
95
+ <div class="callout"><strong>Result:</strong> The full workflow worked against an isolated temporary database. Semantic embeddings were unavailable, so <code>prepare</code> clearly fell back to recent project context. <code>close --dry-run</code> showed the selected source without a model call or database changes. With an SSH port forward to Parmenide, interactive <code>close</code> generated a proposal, accepted approval, and saved it with its source prompt ID.</div>
96
+ <p><code>ph context --memories-only</code> then returned the promoted knowledge and source reference. The generated proposal included plausible details beyond the sample evidence, so users should review and edit proposals before approval. All writes were limited to the temporary test database.</p>
97
+
98
+ <footer>
99
+ <strong>Local sources:</strong> <code>src/context/index.ts</code>, <code>src/types.ts</code>, <code>src/db/index.ts</code>, <code>src/mcp/server.ts</code>, <code>README.md</code>, <code>docs/superpowers/specs/2026-06-12-ph-evolution-design.md</code>, <code>docs/evals/context-retrieval.md</code>.<br>
100
+ This document records the product analysis and initial recommendation. Current implementation status is tracked in the linked work plan and SPEC-016.
101
+ </footer>
102
+ </main>
103
+ </body>
104
+ </html>
@@ -0,0 +1,192 @@
1
+ # Work Plan: Making ph an Operational Memory
2
+
3
+ **Date:** 2026-10-10
4
+ **Status:** Phases 0–3 implemented; Phase 4 deferred until real usage feedback is available.
5
+
6
+ **Product decision:** Guide the `prepare → work → review → promote` cycle by reusing existing retrieval, memories, summaries, and MCP tools.
7
+ **Analysis:** [From Prompt History to Operational Memory](../ph-operational-memory-analysis.html)
8
+
9
+ ## Goal
10
+
11
+ At the start of a task, ph should retrieve relevant prior work and show its sources. At the end, it should help preserve reusable decisions and procedures, always with explicit user approval.
12
+
13
+ Success means reducing context that must be explained again and work that must be repeated, rather than increasing the number of analyzed prompts.
14
+
15
+ ## Current State and Implications
16
+
17
+ - `getProjectContext()` is shared by `ph context`, `ph chat`, and MCP. It supports project summaries, memories, and relevant interactions.
18
+ - Memories include `prompt_ids`, but MCP `save_decision` previously created decisions with `prompt_ids: []`.
19
+ - `project_summaries` aggregates insights and decisions; `memories` preserves the detailed history.
20
+ - `check_project_knowledge` and `get_project_context` are already available through MCP. The first slice should improve reuse of evidence rather than add a second memory system.
21
+ - Deterministic context retrieval tests and a small golden set already exist. The evaluation set should be expanded before retrieval is optimized.
22
+
23
+ ## Architecture
24
+
25
+ ```text
26
+ User task
27
+ │
28
+ ▼
29
+ ph prepare ──► shared retrieval ──► compact brief + sources
30
+ │
31
+ ▼
32
+ AI work
33
+ │
34
+ ▼
35
+ ph close ──► selected prompts ──► knowledge proposals
36
+ │
37
+ user approval
38
+ │
39
+ ▼
40
+ memories(prompt_ids) + project_summaries
41
+ │
42
+ └────► CLI / MCP / next prepare
43
+ ```
44
+
45
+ ## Phases
46
+
47
+ ### Phase 0 — Retrieval Contract and Evaluation
48
+
49
+ **Purpose:** Define what makes a result useful and establish a baseline before changing search behavior.
50
+
51
+ **Activities**
52
+
53
+ - Expand `docs/evals/context-retrieval-golden.json` with queries across multiple projects, covering decisions, resolved bugs, procedures, and models/providers.
54
+ - Label each case with relevant prompt or memory IDs, the project, and examples of misleading results.
55
+ - Record a `Recall@3` baseline and manually review relevance; do not optimize for result volume.
56
+ - Define source references using memory ID, prompt ID, date, tool, and project.
57
+
58
+ **Acceptance criteria**
59
+
60
+ - At least 12 judged queries across at least four projects.
61
+ - Results distinguish “no evidence” from “evidence found.”
62
+ - The evaluation test reports repeatable metrics without calling a generative LLM.
63
+
64
+ ### Phase 1 — `ph prepare`: Prepare for a Task
65
+
66
+ **Interface**
67
+
68
+ ```bash
69
+ ph prepare "add the Wise provider to ph"
70
+ ph prepare "diagnose the SQLite lock" --project picot --limit 5
71
+ ph prepare "evaluate MLX-Serve" --budget 3500
72
+ ```
73
+
74
+ **Activities**
75
+
76
+ - Add `src/commands/prepare.ts` and connect it to `src/cli.ts`.
77
+ - Reuse `getProjectContext()` and `formatProjectContext()`; do not duplicate retrieval or formatting in a new service.
78
+ - Detect the project from the current directory, with an explicit `--project` override.
79
+ - Use the task as a semantic query and provide a clear fallback when Ollama embeddings are unavailable.
80
+ - Print a compact brief with decisions, gotchas, prior work, and sources (`memory #N`, `prompt #N`, date, and tool).
81
+ - Add an output budget. Truncate raw interactions first and preserve source IDs.
82
+ - Keep `ph context` compatible and document the distinction: `context` explores; `prepare` creates a brief for a task.
83
+
84
+ **Acceptance criteria**
85
+
86
+ - `prepare` does not write to the database.
87
+ - It makes no generative LLM call; local embeddings are used only for semantic retrieval.
88
+ - Output is reproducible, bounded by the content budget, and has traceable sources.
89
+ - An explicit `--project` prevents project mixing; a missing detected project gives a clear instruction.
90
+ - A query with no results does not invent knowledge and says so.
91
+
92
+ ### Phase 2 — `ph close`: Propose What to Keep
93
+
94
+ **Interface**
95
+
96
+ ```bash
97
+ ph close --since 3h
98
+ ph close --from 1670 --to 1682
99
+ ph close --dry-run --since 3h
100
+ ```
101
+
102
+ **Activities**
103
+
104
+ - Add `src/commands/close.ts`; reuse `PhDB`, `LLMProvider`, and the existing `save_decision` persistence behavior where applicable.
105
+ - Select inputs explicitly by project and time window or ID range. Show how many prompt/response pairs will be included before generation.
106
+ - Make one optional analysis call to propose zero or more decisions/insights, without promoting them automatically.
107
+ - Show proposed text, sources, and destination fields; allow approval, text editing, or cancellation.
108
+ - After approval, append memories with their source prompt IDs and update `project_summaries`.
109
+ - Extend MCP `save_decision` with optional `promptIds`; validate that IDs exist and belong to the declared project.
110
+ - Avoid new tables or knowledge types in the first release. Store decisions and procedures in existing fields.
111
+
112
+ **Acceptance criteria**
113
+
114
+ - `--dry-run` performs no writes.
115
+ - Cancelling review does not change `memories` or `project_summaries`.
116
+ - Each approved proposal retains at least one source ID.
117
+ - A prompt from another project cannot be attached accidentally.
118
+ - The aggregate summary remains consistent and detailed memories remain append-only.
119
+ - Provider errors, missing providers, and malformed responses do not cause partial promotion.
120
+
121
+ ### Phase 3 — Bring the Workflow to Agents Through MCP
122
+
123
+ **Activities**
124
+
125
+ - Make `check_project_knowledge` semantically relevant by reusing `getProjectContext()` instead of substring matching memories alone.
126
+ - Include sources and a clear outcome: knowledge found, partial evidence, or no evidence.
127
+ - Reuse MCP `save_decision` for end-of-task promotion, with source references.
128
+ - Document a client-neutral agent workflow for Codex, OpenCode, and other MCP clients.
129
+ - Do not inject context into every prompt automatically; the client or user invokes preflight when a meaningful task begins.
130
+
131
+ **Acceptance criteria**
132
+
133
+ - The same evaluation case returns the same evidence from `ph prepare` and MCP.
134
+ - MCP tools do not expose content from other projects.
135
+ - Promotion preserves source `prompt_ids` validated by the server.
136
+
137
+ ### Phase 4 — Feedback and Knowledge Maintenance
138
+
139
+ **Deferred until Phases 1–3 have been used on real work.**
140
+
141
+ - Add `ph feedback <memory-id> useful|irrelevant|stale` and an MCP equivalent only if agents need them.
142
+ - Decide whether feedback belongs in a separate event table or updateable memory fields; preserve history if judgments can change over time.
143
+ - Use feedback and access counts for ranking and review, not automatic deletion.
144
+ - Add a review command for old or contradicted decisions, with sources and last verification date.
145
+
146
+ **Gate:** proceed only after `prepare` is used on real tasks and some results are confirmed useful. Do not add complex ranking before feedback exists.
147
+
148
+ ## Decisions and Trade-offs
149
+
150
+ | Topic | Decision | Rationale and cost |
151
+ |---|---|---|
152
+ | Entry points | Add `prepare` and `close`, keep `context` | The names describe two work moments; existing scripts remain compatible. |
153
+ | Promotion | Require human approval before writes | Adds a step while preventing false or noisy permanent memory. |
154
+ | Sources | Reuse `MemoryEntry.prompt_ids` | The field already exists; the main gap was MCP persistence. |
155
+ | Data model | No new tables in Phases 0–3 | Existing summaries, insights, decisions, and sources are sufficient for the first validation. |
156
+ | Retrieval | Prioritize relevance and project scoping before personalization | Reduces cross-project contamination and supports deterministic measurement. |
157
+ | Automation | No global auto-injection or auto-promotion in the MVP | Avoids noise, wasted tokens, and silent changes. |
158
+
159
+ ## Cost, Rate Limits, and Latency
160
+
161
+ - **Prepare:** SQLite is local. Semantic retrieval uses the configured embedding endpoint (Ollama by default); it adds a request and local-server latency, but no generative cloud call.
162
+ - **Close:** One LLM request creates proposals. OpenRouter may incur cost and rate limits; MLX-Serve depends on the tunnel, loaded model, and available memory. Users choose the configured provider and approve before writing.
163
+ - **Budget:** Limit included prompt/response text, show the number of sources, and apply an explicit budget to the `prepare` brief. Do not hide truncation.
164
+ - **Degraded operation:** If embeddings or the provider are unavailable, keep search and manual saving usable and identify the unavailable step without fabricating results.
165
+
166
+ ## Definition of Done
167
+
168
+ - Existing tests remain green. New tests cover sources/projects, output budget, dry-run, cancellation, and `promptIds` validation.
169
+ - Golden set has at least 12 queries with an initial `Recall@3 ≥ 0.8` target and manual review of misses. Recalibrate if the labels show that the set is insufficient.
170
+ - Three real tasks across different projects complete the workflow; the user can judge whether the brief prevented repeated decisions or investigation.
171
+ - Every promoted item links to its evidence; unapproved work never changes curated memory.
172
+ - README and manual document `prepare`, `close`, provider configuration, costs, and offline behavior.
173
+
174
+ ## Usage Check (2026-10-10)
175
+
176
+ Using an isolated temporary database seeded with one sample prompt:
177
+
178
+ - `ph prepare "project cache path" --project ph --limit 3 --budget 1200` displayed the matching prompt and response with their source ID. Ollama embeddings were unavailable, and the command clearly reported that it was using recent project context instead.
179
+ - `ph close --from 1 --to 1 --project ph --dry-run` displayed the selected prompt and response, then confirmed that it made no model call and no database changes.
180
+ - The configured direct localhost route to MLX-Serve failed. An SSH port forward to Parmenide (`18034 → 127.0.0.1:11234`) restored connectivity. Interactive `ph close` generated a proposal, accepted approval, and saved memory `#1` linked to prompt `#1` in the temporary database.
181
+ - `ph context --memories-only --project ph` then returned the saved summary, insights, decisions, and `prompt #1` provenance. The generated proposal added plausible details beyond the sample evidence, reinforcing the need to inspect and edit proposals before approval.
182
+ - The full usage path was exercised on the temporary database only; no user history or project memory was changed.
183
+
184
+ ## Delivery Order
185
+
186
+ 1. Phase 0: evaluation cases and source contract.
187
+ 2. Phase 1: read-only `prepare`.
188
+ 3. Phase 2: `close` with preview, approval, and provenance.
189
+ 4. Phase 3: shared retrieval and promotion through MCP.
190
+ 5. Phase 4: explicit feedback and review after real usage.
191
+
192
+ Each phase can ship as a separate change. The first operational version is complete with Phases 0–3; Phase 4 depends on observing real usage and can be planned separately.
@@ -2,81 +2,109 @@
2
2
 
3
3
  - **ID**: SPEC-001
4
4
  - **Cluster**: Core
5
- - **Status**: Implemented (baseline)
6
- - **Date**: 2026-08-08
7
- - **Source**: reverse-engineered from code (files listed in §8)
5
+ - **Status**: Implemented (plain-text daily workflow)
6
+ - **Date**: 2026-10-22
7
+ - **Source**: current repository behavior
8
8
 
9
9
  ## 1. Purpose
10
- `ph` is a transparent observability layer for AI CLI tools: every prompt+response
11
- is captured to a local SQLite DB (SPEC-002), analyzed (SPEC-006), and made
12
- browsable via TUI (SPEC-012), CLI commands, MCP (SPEC-011) and HTTP (SPEC-010).
13
- This spec covers the entry point and the command dispatch architecture.
10
+
11
+ PH captures AI CLI interactions, finds earlier work, retrieves project context,
12
+ and supports explicit review of durable project knowledge. The everyday
13
+ interface is a small plain-text CLI; maintenance and integration commands are
14
+ available separately through `ph help --all`.
14
15
 
15
16
  ## 2. Scope
16
- - **In scope**: cli.ts main(), command resolution, wrapper-mode fallback, config
17
- loading order, TUI bootstrap.
18
- - **Out of scope**: individual commands (their own specs), the TUI internals.
19
- - **Entry points**: `ph` (no args → TUI), `ph <command>`, `ph <tool> "prompt"` (wrapper).
20
-
21
- ## 3. Data Model
22
- - `argv` split into `command` (first non-flag arg) + `cmdArgs` + `preArgs`
23
- (ph-specific flags before the command, e.g. `--ph-tag`).
24
- - `PhConfig` (src/config/index.ts:5) loaded before dispatch; `geminiApiKey`
25
- is copied to `process.env.GEMINI_API_KEY` (cli.ts:153-155).
26
- - DB path resolution: `PH_DB` env > `cfg.dbPath` > `defaultPath()`
27
- (cli.ts:157).
28
-
29
- ## 4. Flows
30
-
31
- ### 4.1 Dispatch (src/cli.ts:148-441)
32
- 1. Load config; set env; resolve dbPath.
33
- 2. No args + TTY → render BrowseApp in alt-screen, wait for exit, optional
34
- rerun (cli.ts:159-186).
35
- 3. Find first non-flag arg; flags `--ph-tag`/`--ph-role` consume their value
36
- (cli.ts:190-203).
37
- 4. Switch on the command name: ~25 cases (search, context, last, sessions,
38
- stats, cluster, analyze*, cleanup*, star, export, import, analyze, mcp,
39
- server, remote, log, embed-all, vacuum, config, _bg-analyze, browse, chat,
40
- timeline, ollama-models, help).
41
- 5. Unknown command → wrapper mode: `cmdWrap(dbPath, command, [...preArgs,
42
- ...cmdArgs], cfg)` (cli.ts:436-439).
43
-
44
- ### 4.2 Wrapper mode (SPEC-003)
45
- Unknown first arg = a real binary (`claude`, `gemini`, …): run it and capture.
46
-
47
- ## 5. Invariants & Business rules
48
- - ESM only, `.js` import extensions (package.json `"type": "module"`).
49
- - Manual arg parsing (`parseFlags`, src/commands/_utils.ts:1) — no commander.
50
- - Every command handler owns its `PhDB` instance and closes it
51
- (`new PhDB(...)` … `db.close()` per case).
52
- - `main()` catches everything: `ph: <message>` on stderr, exit 1 (cli.ts:443-446).
53
-
54
- ## 6. UI / UX surface
55
- USAGE text is a single ~200-line template literal (cli.ts:38-140); `ph --help`,
56
- `-h`, `help` and non-TTY no-arg all print it.
57
-
58
- ## 7. Acceptance criteria (Given/When/Then)
59
- - **G1**: Given `ph search foo`, When main() runs, Then the `search` case opens a
60
- PhDB, calls `cmdSearch` and closes the DB (cli.ts:250-253).
61
- - **G2**: Given `ph claude "hello"` (unknown command), When main() runs, Then
62
- `cmdWrap` receives tool=`claude` and args `["hello"]` (cli.ts:436-439).
63
- - **G3**: Given `ph` with no args on a non-TTY stdin, When main() runs, Then the
64
- USAGE text is printed and the process exits 0 (cli.ts:183-186).
65
- - **G4**: Given `--ph-tag auth claude "x"`, When parsing, Then `auth` is consumed
66
- as the tag value and `claude` is the command (cli.ts:192-194).
67
-
68
- ## 8. Key implementation map
17
+
18
+ - **In scope**: CLI startup, concise and advanced help, command dispatch,
19
+ compatibility aliases, wrapper fallback, and task-aware context retrieval.
20
+ - **Out of scope**: command internals outside context, MCP/HTTP protocols, and
21
+ import formats.
22
+ - **Entry points**: `ph` prints a concise usage guide; `ph <tool> [args...]`
23
+ wraps and captures an AI CLI; `search`, `show`, `context`, and `close` serve the daily
24
+ history and memory workflows.
25
+
26
+ ## 3. Dispatch Rules
27
+
28
+ 1. Load config and resolve the database path.
29
+ 2. With no arguments, print the short guide and exit without opening a database
30
+ or starting an interactive UI.
31
+ 3. `ph --help` and `ph help` print the short guide. `ph --help --all` and
32
+ `ph help --all` print the full maintenance and integration catalog.
33
+ 4. `context` and the legacy `prepare` command share task-aware retrieval and
34
+ its recent-history fallback.
35
+ 5. `close` defaults to reviewing the last three hours; explicit time ranges
36
+ and prompt ID ranges remain supported.
37
+ 6. `browse` remains a text-only compatibility alias for recent interactions.
38
+ `search -i` remains accepted and prints normal text results.
39
+ 7. Unknown commands fall through to transparent wrapper mode.
40
+
41
+ ## 4. User-Facing Jobs
42
+
43
+ | Job | Primary command | Contract |
44
+ |---|---|---|
45
+ | Setup | `ph setup [tool...]` | Detect supported installed tools by default and install native capture integrations while preserving existing configuration |
46
+ | Capture | Native tool hook after setup; `ph <tool> [args...]` remains optional | Capture completed exchanges without changing the user's normal AI CLI invocation |
47
+ | Find | `ph search <query>` | Search the current project, show five relevant matches; use `--all` to broaden |
48
+ | Inspect | `ph show <id>` | Display the complete captured interaction and its analysis |
49
+ | Resume | `ph context "task"` | Optional explicit retrieval of project knowledge and relevant interactions |
50
+ | Review | `ph close` | Optional review of recent work; propose durable knowledge and require explicit approval |
51
+
52
+ Daily use requires setup once, then normal use of the supported AI CLI; search
53
+ is the primary PH command and `show` opens any result in full. `prepare` is a compatibility alias for
54
+ `context`. There is no TUI in the runtime package. History can also be read
55
+ with `last` or the `browse` compatibility alias.
56
+
57
+ ## 5. Invariants
58
+
59
+ - ESM only; relative imports use `.js` extensions.
60
+ - Existing advanced command names remain available unless separately removed.
61
+ - Capture and full-text search do not require an AI provider.
62
+ - `setup` writes only PH hook entries and preserves other JSON configuration;
63
+ rerunning setup does not duplicate its entries.
64
+ - Setup does not import prior sessions or start an analysis provider.
65
+ - Retrieval labels its recent-history fallback; it does not silently claim
66
+ semantic matching when embeddings are unavailable.
67
+ - `close` does not call a provider or mutate storage without a TTY and explicit
68
+ approval of proposed knowledge.
69
+
70
+ ## 6. Acceptance Criteria
71
+
72
+ - **G1**: Given `ph` in either a TTY or a pipe, when it starts, then it prints
73
+ the same short guide, exits successfully, and emits no alternate-screen or
74
+ interactive terminal controls.
75
+ - **G2**: Given `ph help --all`, when help is requested, then the full advanced
76
+ command catalog is shown.
77
+ - **G3**: Given `ph context "cache timeout"` in a detected project, when semantic
78
+ embeddings are unavailable, then recent project evidence is shown with an
79
+ explicit fallback label and no database writes occur.
80
+ - **G4**: Given `ph prepare "cache timeout"`, when dispatched, then the same
81
+ task-aware context path and output are used.
82
+ - **G5**: Given `ph close --dry-run` with no explicit range, when the project
83
+ contains interactions from the last three hours, then they are selected and
84
+ shown without provider calls or database writes.
85
+ - **G6**: Given `ph browse` or `ph search -i "cache"`, when invoked, then
86
+ matching/recent plain-text results are printed without an interactive UI.
87
+ - **G7**: Given an existing Claude/Codex/Gemini JSON configuration, when
88
+ `ph setup <tool>` runs, then its existing keys are preserved, one PH hook is
89
+ installed, and rerunning setup does not duplicate that hook; OpenCode's
90
+ existing `ph-plugin.ts` is left untouched if it differs from PH's plugin.
91
+ - **G8**: Given a supported tool name, when `ph setup` is called with explicit
92
+ tool names, then only those integrations are installed; without names, only
93
+ installed supported CLIs are detected and configured.
94
+
95
+ ## 7. Implementation Map
96
+
69
97
  | Concern | File(s) |
70
98
  |---|---|
71
- | Entry + dispatch + USAGE | src/cli.ts:38-441 |
72
- | Config load/save | src/config/index.ts:26-40 |
73
- | Flag parsing | src/commands/_utils.ts:1-30 |
74
- | Shared TUI bootstrap | src/cli.ts (`openBrowser`, `runRerun`) |
75
-
76
- ## 9. Open questions / discrepancies
77
- - `--ph-debug` is listed in USAGE but only consumed by wrapper paths (inline/pty
78
- debug logs); no validation if used with non-wrapper commands.
79
-
80
- ## 10. Related
81
- - All other specs (commands dispatch into each), SPEC-012 (BrowseApp),
82
- SPEC-003 (wrapper mode). CLI dispatch tests remain part of SPEC-ISSUES-007.
99
+ | Startup, help, dispatch | `src/cli.ts` |
100
+ | Search and `-i` compatibility | `src/commands/search.ts` |
101
+ | Task-aware context | `src/commands/context.ts`, `src/knowledge/task-context.ts` |
102
+ | Three-hour review default | `src/commands/close.ts` |
103
+ | Native capture setup | `src/commands/setup.ts` |
104
+ | CLI / operational memory tests | `src/commands/__tests__/operational-memory.test.ts` |
105
+
106
+ ## 8. Related
107
+
108
+ `SPEC-003` (capture wrapper), `SPEC-005` (search), `SPEC-016` (operational
109
+ memory), and `SPEC-012` (retired history browser; retained as historical
110
+ documentation).
@@ -2,7 +2,7 @@
2
2
 
3
3
  - **ID**: SPEC-002
4
4
  - **Cluster**: DB
5
- - **Status**: Implemented (baseline)
5
+ - **Status**: Implemented; internal repository extraction in SPEC-017
6
6
  - **Date**: 2026-08-08
7
7
  - **Source**: reverse-engineered from code (files listed in §8)
8
8
 
@@ -28,6 +28,9 @@ effort migrations, zero ORM.
28
28
  - `embeddings` (legacy BLOB, 87-91) + `vec_embeddings` vec0 float[768] (100-104).
29
29
  - `memories` (106-121) append-only per project; `project_summaries` (PhDB.PROJECT_SUMMARIES_SCHEMA, :123);
30
30
  `prompts_archive` (PhDB.ARCHIVE_SCHEMA, :124).
31
+ - `ph_meta` stores a persistent database UUID and one-time migration markers.
32
+ The `search_metadata` backfill marker prevents reopening PH from rescanning
33
+ rows whose derived metadata is legitimately empty.
31
34
  - `PromptEntry` / `PromptMetadata` / `MemoryEntry` / `ProjectSummary` types
32
35
  (src/types.ts:1-52).
33
36
 
@@ -77,18 +80,28 @@ None — library layer consumed by commands, TUI, MCP and HTTP server.
77
80
  consistent with the tables (src/db/index.ts:410+).
78
81
  - **G6**: Given a fresh DB, When opened, Then `vec_embeddings` exists as a vec0
79
82
  table with float[768] (src/db/index.ts:95-104).
83
+ - **G7**: Given an existing prompt database, When the searchable-metadata
84
+ migration completes, Then its marker is persisted and a later open does not
85
+ rerun the backfill query; the database UUID survives reopen and differs for
86
+ a separate database file.
80
87
 
81
88
  ## 8. Key implementation map
82
89
  | Concern | File(s) |
83
90
  |---|---|
84
91
  | Schema + migrations | src/db/index.ts:47-196 |
85
92
  | CRUD + search + sync primitives | src/db/index.ts:198-531 |
86
- | Memories + summaries | src/db/index.ts:535-720 |
87
- | Archive | src/db/index.ts:464-518 |
93
+ | Memory and summary persistence | src/db/memory-repository.ts |
94
+ | Archive persistence | src/db/archive-repository.ts |
95
+ | Public facade and migrations | src/db/index.ts |
88
96
  | Semantic vector index | src/db/semantic-index.ts |
89
97
  | Types | src/types.ts:1-52 |
90
98
 
91
99
  ## 9. Open questions / discrepancies
100
+ - Routine `PhDB` construction still runs schema probes and a JSON query across
101
+ prompts missing `$schema_version`. The search-metadata backfill is one-time,
102
+ but remaining migration checks scale with history and repeat for each command
103
+ and capture hook. Track schema migrations explicitly to bound normal startup
104
+ work (SPEC-ISSUES-027).
92
105
  - **Architecture decision (2026-10-09)**: keep `PhDB` as the single SQLite adapter
93
106
  for now. Context consumers depend on the focused `ProjectContextStore` interface
94
107
  (`src/context/index.ts`). Vector encoding, compatibility storage, and KNN
@@ -96,6 +109,12 @@ None — library layer consumed by commands, TUI, MCP and HTTP server.
96
109
  methods as the adapter. Scope behavior has an integration test. Keep unrelated
97
110
  CRUD/memory/archive methods together until a second adapter or concrete
98
111
  independent migration/testing seam justifies further division.
112
+ - **Architecture decision (2026-10-22, SPEC-017)**: the atomic memory-promotion
113
+ operation now justifies internal responsibility seams. Keep prompt CRUD, FTS,
114
+ schema, and migrations together in `PhDB`; move memory/summary and archive
115
+ operations into internal repositories sharing its connection. Keep `PhDB`
116
+ source-compatible, preserve the single transaction boundary, and do not
117
+ change the schema.
99
118
  - `response` column via ALTER (SPEC-ISSUES-001).
100
119
  - `memories.prompt_ids` possibly unused after summaries (SPEC-ISSUES-014).
101
120
  - `delete` (427) and `deleteById` (435) coexist — duplicate deletion paths.
@@ -2,7 +2,7 @@
2
2
 
3
3
  - **ID**: SPEC-003
4
4
  - **Cluster**: Capture
5
- - **Status**: Implemented (baseline)
5
+ - **Status**: Implemented; shared live lifecycle defined by SPEC-019
6
6
  - **Date**: 2026-08-08
7
7
  - **Source**: reverse-engineered from code (files listed in §8)
8
8
 
@@ -37,15 +37,20 @@ or `ph log`. Plus the OpenCode plugin for real-time capture.
37
37
  sequences. On Enter: finalize previous response, call `onPrompt`.
38
38
  4. On PTY exit: finalize last response, restore stdin, resolve with exitCode.
39
39
 
40
- ### 4.2 Inline (src/runner/inline.ts:37)
41
- `runInline` captures args → `extractPrompt(args)` (:8), runs the binary
42
- non-interactively (spawnSync), records exit code, then `db.insert`.
40
+ ### 4.2 Inline (src/runner/inline.ts)
41
+ `runInline` captures args → `extractPrompt(args)`, persists a normalized record
42
+ with lifecycle status, spawns the tool, forwards stdout unchanged while
43
+ collecting it as the interaction response, then persists response and exit
44
+ code. The shared completion helper dispatches configured analysis and remote
45
+ sync as the PTY and direct-log paths. Configured remote pushes have a
46
+ five-second timeout; invalid URLs do not prevent local capture.
43
47
 
44
48
  ### 4.3 Direct log (src/commands/log.ts:9-70)
45
49
  `ph log --tool <t> --prompt <p> [--response <r>]` builds the entry (project
46
- detection, language detection, topic extraction), inserts, then optionally
47
- spawns background analysis (SPEC-006) and a fire-and-forget remote push
48
- (SPEC-010).
50
+ detection, language detection, topic extraction), inserts, then dispatches
51
+ configured analysis and a remote push with a five-second timeout through the
52
+ shared live capture lifecycle (SPEC-019). Lifecycle states are stored on the
53
+ interaction and shown by `ph status`.
49
54
 
50
55
  ### 4.4 Hooks + plugin
51
56
  - `hooks/claude/ph-hook.sh`, `hooks/gemini/ph-hook.sh` — shell scripts invoked
@@ -63,8 +68,10 @@ spawns background analysis (SPEC-006) and a fire-and-forget remote push
63
68
  - Capture never blocks the wrapped tool (background processes for analysis/push).
64
69
  - Binary resolution: `resolveRealBinary(tool)` maps known tool names
65
70
  (src/runner/inline.ts:15).
66
- - All supported capture adapters produce the same normalized PromptEntry shape;
67
- source-specific metadata remains attached to that record.
71
+ - All live adapters pass through the shared lifecycle preparation/completion
72
+ seam; source-specific metadata remains attached to the normalized record.
73
+ - Inline wrapper output is both visible to the caller and stored as `response`;
74
+ child exit status is retained. Empty output is a valid completed response.
68
75
 
69
76
  ## 6. UI / UX surface
70
77
  Transparent: the wrapped tool's own output is forwarded verbatim; ph itself
@@ -85,6 +92,12 @@ prints only capture feedback.
85
92
  - **G5**: Given a capture with a project marker and adapter metadata, When
86
93
  `createCaptureRecord` builds it, Then it includes detected project/language,
87
94
  source metadata, and common fields (src/capture/index.ts).
95
+ - **G6**: Given inline child stdout and a non-zero exit, When the wrapper
96
+ completes, Then stdout is forwarded and stored as response and the exit code
97
+ is retained (`src/runner/inline.test.ts`).
98
+ - **G7**: Given analysis or remote sync is configured, When live capture enters
99
+ through log, inline, or PTY, Then all paths initialize and dispatch the same
100
+ lifecycle effects (`src/capture/lifecycle.ts`, SPEC-019).
88
101
 
89
102
  ## 8. Key implementation map
90
103
  | Concern | File(s) |