@getrift/rift 0.1.0-beta.20 → 0.1.0-beta.22
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.
- package/README.md +7 -3
- package/dist/src/capture/auto-capture.d.ts +105 -4
- package/dist/src/capture/auto-capture.d.ts.map +1 -1
- package/dist/src/capture/auto-capture.js +313 -34
- package/dist/src/capture/auto-capture.js.map +1 -1
- package/dist/src/capture/claude-cli-triage-provider.d.ts +28 -0
- package/dist/src/capture/claude-cli-triage-provider.d.ts.map +1 -0
- package/dist/src/capture/claude-cli-triage-provider.js +88 -0
- package/dist/src/capture/claude-cli-triage-provider.js.map +1 -0
- package/dist/src/capture/codex-cli-triage-provider.d.ts.map +1 -1
- package/dist/src/capture/codex-cli-triage-provider.js +1 -33
- package/dist/src/capture/codex-cli-triage-provider.js.map +1 -1
- package/dist/src/capture/cursor-capture.d.ts +89 -0
- package/dist/src/capture/cursor-capture.d.ts.map +1 -0
- package/dist/src/capture/cursor-capture.js +121 -0
- package/dist/src/capture/cursor-capture.js.map +1 -0
- package/dist/src/capture/observability.d.ts +30 -0
- package/dist/src/capture/observability.d.ts.map +1 -1
- package/dist/src/capture/observability.js +29 -0
- package/dist/src/capture/observability.js.map +1 -1
- package/dist/src/capture/sources.d.ts +41 -3
- package/dist/src/capture/sources.d.ts.map +1 -1
- package/dist/src/capture/sources.js +43 -1
- package/dist/src/capture/sources.js.map +1 -1
- package/dist/src/capture/triage-classification.d.ts +69 -0
- package/dist/src/capture/triage-classification.d.ts.map +1 -0
- package/dist/src/capture/triage-classification.js +62 -0
- package/dist/src/capture/triage-classification.js.map +1 -0
- package/dist/src/capture/triage-provider-factory.d.ts +36 -0
- package/dist/src/capture/triage-provider-factory.d.ts.map +1 -0
- package/dist/src/capture/triage-provider-factory.js +55 -0
- package/dist/src/capture/triage-provider-factory.js.map +1 -0
- package/dist/src/capture/triage.d.ts +1 -1
- package/dist/src/capture/triage.d.ts.map +1 -1
- package/dist/src/capture/triage.js +8 -6
- package/dist/src/capture/triage.js.map +1 -1
- package/dist/src/cli/commands/capture.d.ts.map +1 -1
- package/dist/src/cli/commands/capture.js +72 -17
- package/dist/src/cli/commands/capture.js.map +1 -1
- package/dist/src/cli/commands/chunk-backfill.d.ts +13 -0
- package/dist/src/cli/commands/chunk-backfill.d.ts.map +1 -0
- package/dist/src/cli/commands/chunk-backfill.js +157 -0
- package/dist/src/cli/commands/chunk-backfill.js.map +1 -0
- package/dist/src/cli/commands/cursor-probe.d.ts +20 -0
- package/dist/src/cli/commands/cursor-probe.d.ts.map +1 -0
- package/dist/src/cli/commands/cursor-probe.js +162 -0
- package/dist/src/cli/commands/cursor-probe.js.map +1 -0
- package/dist/src/cli/commands/menubar.d.ts +50 -0
- package/dist/src/cli/commands/menubar.d.ts.map +1 -1
- package/dist/src/cli/commands/menubar.js +224 -16
- package/dist/src/cli/commands/menubar.js.map +1 -1
- package/dist/src/cli/commands/onboard.d.ts +36 -7
- package/dist/src/cli/commands/onboard.d.ts.map +1 -1
- package/dist/src/cli/commands/onboard.js +256 -53
- package/dist/src/cli/commands/onboard.js.map +1 -1
- package/dist/src/cli/commands/status.d.ts.map +1 -1
- package/dist/src/cli/commands/status.js +16 -0
- package/dist/src/cli/commands/status.js.map +1 -1
- package/dist/src/cli/commands/update.d.ts +34 -1
- package/dist/src/cli/commands/update.d.ts.map +1 -1
- package/dist/src/cli/commands/update.js +179 -2
- package/dist/src/cli/commands/update.js.map +1 -1
- package/dist/src/cli/index.d.ts.map +1 -1
- package/dist/src/cli/index.js +4 -0
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/cli/postinstall-menubar.d.ts.map +1 -1
- package/dist/src/cli/postinstall-menubar.js +14 -0
- package/dist/src/cli/postinstall-menubar.js.map +1 -1
- package/dist/src/cli/status/friend-header.d.ts +18 -0
- package/dist/src/cli/status/friend-header.d.ts.map +1 -1
- package/dist/src/cli/status/friend-header.js +137 -0
- package/dist/src/cli/status/friend-header.js.map +1 -1
- package/dist/src/cli/status/local-signals.d.ts +41 -0
- package/dist/src/cli/status/local-signals.d.ts.map +1 -1
- package/dist/src/cli/status/local-signals.js +48 -0
- package/dist/src/cli/status/local-signals.js.map +1 -1
- package/dist/src/config/schema.d.ts +220 -14
- package/dist/src/config/schema.d.ts.map +1 -1
- package/dist/src/config/schema.js +82 -7
- package/dist/src/config/schema.js.map +1 -1
- package/dist/src/diagnostics/claude-preflight.d.ts +34 -0
- package/dist/src/diagnostics/claude-preflight.d.ts.map +1 -0
- package/dist/src/diagnostics/claude-preflight.js +89 -0
- package/dist/src/diagnostics/claude-preflight.js.map +1 -0
- package/dist/src/diagnostics/codex-preflight.d.ts +1 -1
- package/dist/src/diagnostics/codex-preflight.d.ts.map +1 -1
- package/dist/src/diagnostics/codex-preflight.js +14 -0
- package/dist/src/diagnostics/codex-preflight.js.map +1 -1
- package/dist/src/diagnostics/doctor.d.ts +9 -1
- package/dist/src/diagnostics/doctor.d.ts.map +1 -1
- package/dist/src/diagnostics/doctor.js +57 -2
- package/dist/src/diagnostics/doctor.js.map +1 -1
- package/dist/src/ingestion/chunk-meta.d.ts +85 -0
- package/dist/src/ingestion/chunk-meta.d.ts.map +1 -0
- package/dist/src/ingestion/chunk-meta.js +167 -0
- package/dist/src/ingestion/chunk-meta.js.map +1 -0
- package/dist/src/ingestion/chunk-text.d.ts +39 -0
- package/dist/src/ingestion/chunk-text.d.ts.map +1 -0
- package/dist/src/ingestion/chunk-text.js +114 -0
- package/dist/src/ingestion/chunk-text.js.map +1 -0
- package/dist/src/ingestion/cursor/cursor-store.d.ts +177 -0
- package/dist/src/ingestion/cursor/cursor-store.d.ts.map +1 -0
- package/dist/src/ingestion/cursor/cursor-store.js +243 -0
- package/dist/src/ingestion/cursor/cursor-store.js.map +1 -0
- package/dist/src/ingestion/cursor/enrich-roots.d.ts +16 -0
- package/dist/src/ingestion/cursor/enrich-roots.d.ts.map +1 -0
- package/dist/src/ingestion/cursor/enrich-roots.js +22 -0
- package/dist/src/ingestion/cursor/enrich-roots.js.map +1 -0
- package/dist/src/ingestion/cursor/vscdb-reader.d.ts +32 -0
- package/dist/src/ingestion/cursor/vscdb-reader.d.ts.map +1 -0
- package/dist/src/ingestion/cursor/vscdb-reader.js +113 -0
- package/dist/src/ingestion/cursor/vscdb-reader.js.map +1 -0
- package/dist/src/ingestion/cursor/workspace-root.d.ts +96 -0
- package/dist/src/ingestion/cursor/workspace-root.d.ts.map +1 -0
- package/dist/src/ingestion/cursor/workspace-root.js +187 -0
- package/dist/src/ingestion/cursor/workspace-root.js.map +1 -0
- package/dist/src/ingestion/indexer.d.ts.map +1 -1
- package/dist/src/ingestion/indexer.js +41 -32
- package/dist/src/ingestion/indexer.js.map +1 -1
- package/dist/src/jobs/handlers/compact.d.ts.map +1 -1
- package/dist/src/jobs/handlers/compact.js +9 -4
- package/dist/src/jobs/handlers/compact.js.map +1 -1
- package/dist/src/jobs/handlers/ingest.d.ts.map +1 -1
- package/dist/src/jobs/handlers/ingest.js +60 -30
- package/dist/src/jobs/handlers/ingest.js.map +1 -1
- package/dist/src/jobs/handlers/reconcile.d.ts.map +1 -1
- package/dist/src/jobs/handlers/reconcile.js +128 -45
- package/dist/src/jobs/handlers/reconcile.js.map +1 -1
- package/dist/src/jobs/handlers/save.d.ts.map +1 -1
- package/dist/src/jobs/handlers/save.js +122 -72
- package/dist/src/jobs/handlers/save.js.map +1 -1
- package/dist/src/jobs/types.d.ts +1 -1
- package/dist/src/main.js +26 -15
- package/dist/src/main.js.map +1 -1
- package/dist/src/mcp/server.d.ts.map +1 -1
- package/dist/src/mcp/server.js +10 -3
- package/dist/src/mcp/server.js.map +1 -1
- package/dist/src/mcp/tools/context-pack.d.ts.map +1 -1
- package/dist/src/mcp/tools/context-pack.js +7 -1
- package/dist/src/mcp/tools/context-pack.js.map +1 -1
- package/dist/src/mcp/tools/conversations-search.d.ts +1 -1
- package/dist/src/mcp/tools/conversations-search.d.ts.map +1 -1
- package/dist/src/mcp/tools/conversations-search.js +7 -1
- package/dist/src/mcp/tools/conversations-search.js.map +1 -1
- package/dist/src/mcp/tools/evidence-feedback.d.ts +60 -0
- package/dist/src/mcp/tools/evidence-feedback.d.ts.map +1 -0
- package/dist/src/mcp/tools/evidence-feedback.js +62 -0
- package/dist/src/mcp/tools/evidence-feedback.js.map +1 -0
- package/dist/src/mcp/tools/log-outcome.d.ts +72 -0
- package/dist/src/mcp/tools/log-outcome.d.ts.map +1 -0
- package/dist/src/mcp/tools/log-outcome.js +59 -0
- package/dist/src/mcp/tools/log-outcome.js.map +1 -0
- package/dist/src/mcp/tools/open-evidence.d.ts +37 -0
- package/dist/src/mcp/tools/open-evidence.d.ts.map +1 -0
- package/dist/src/mcp/tools/open-evidence.js +72 -0
- package/dist/src/mcp/tools/open-evidence.js.map +1 -0
- package/dist/src/mcp/tools/save.d.ts +7 -2
- package/dist/src/mcp/tools/save.d.ts.map +1 -1
- package/dist/src/mcp/tools/save.js +7 -2
- package/dist/src/mcp/tools/save.js.map +1 -1
- package/dist/src/mcp/tools/search.d.ts.map +1 -1
- package/dist/src/mcp/tools/search.js +7 -1
- package/dist/src/mcp/tools/search.js.map +1 -1
- package/dist/src/observability/retrieval-feedback.d.ts +82 -0
- package/dist/src/observability/retrieval-feedback.d.ts.map +1 -0
- package/dist/src/observability/retrieval-feedback.js +231 -0
- package/dist/src/observability/retrieval-feedback.js.map +1 -0
- package/dist/src/observability/rift-context.d.ts.map +1 -1
- package/dist/src/observability/rift-context.js +3 -0
- package/dist/src/observability/rift-context.js.map +1 -1
- package/dist/src/observability/tool-usage-stats.d.ts +13 -0
- package/dist/src/observability/tool-usage-stats.d.ts.map +1 -1
- package/dist/src/observability/tool-usage-stats.js +15 -0
- package/dist/src/observability/tool-usage-stats.js.map +1 -1
- package/dist/src/observability/tool-usage.d.ts +56 -0
- package/dist/src/observability/tool-usage.d.ts.map +1 -1
- package/dist/src/observability/tool-usage.js +86 -0
- package/dist/src/observability/tool-usage.js.map +1 -1
- package/dist/src/providers/claude-cli-metadata-extraction.d.ts +47 -0
- package/dist/src/providers/claude-cli-metadata-extraction.d.ts.map +1 -0
- package/dist/src/providers/claude-cli-metadata-extraction.js +120 -0
- package/dist/src/providers/claude-cli-metadata-extraction.js.map +1 -0
- package/dist/src/providers/claude-cli-runner.d.ts +92 -0
- package/dist/src/providers/claude-cli-runner.d.ts.map +1 -0
- package/dist/src/providers/claude-cli-runner.js +598 -0
- package/dist/src/providers/claude-cli-runner.js.map +1 -0
- package/dist/src/providers/codex-cli-metadata-extraction.d.ts.map +1 -1
- package/dist/src/providers/codex-cli-metadata-extraction.js +1 -40
- package/dist/src/providers/codex-cli-metadata-extraction.js.map +1 -1
- package/dist/src/providers/codex-cli-runner.d.ts +7 -0
- package/dist/src/providers/codex-cli-runner.d.ts.map +1 -1
- package/dist/src/providers/codex-cli-runner.js +131 -5
- package/dist/src/providers/codex-cli-runner.js.map +1 -1
- package/dist/src/providers/conversation-generation.d.ts +10 -0
- package/dist/src/providers/conversation-generation.d.ts.map +1 -1
- package/dist/src/providers/conversation-generation.js +54 -13
- package/dist/src/providers/conversation-generation.js.map +1 -1
- package/dist/src/providers/openai-metadata-extraction.d.ts +48 -1
- package/dist/src/providers/openai-metadata-extraction.d.ts.map +1 -1
- package/dist/src/providers/openai-metadata-extraction.js +51 -2
- package/dist/src/providers/openai-metadata-extraction.js.map +1 -1
- package/dist/src/providers/types.d.ts +1 -1
- package/dist/src/providers/types.d.ts.map +1 -1
- package/dist/src/providers/types.js +4 -0
- package/dist/src/providers/types.js.map +1 -1
- package/dist/src/retrieval/compact.d.ts +81 -0
- package/dist/src/retrieval/compact.d.ts.map +1 -1
- package/dist/src/retrieval/compact.js +248 -8
- package/dist/src/retrieval/compact.js.map +1 -1
- package/dist/src/retrieval/context-pack.d.ts.map +1 -1
- package/dist/src/retrieval/context-pack.js +28 -14
- package/dist/src/retrieval/context-pack.js.map +1 -1
- package/dist/src/retrieval/evidence-key.d.ts +48 -0
- package/dist/src/retrieval/evidence-key.d.ts.map +1 -0
- package/dist/src/retrieval/evidence-key.js +131 -0
- package/dist/src/retrieval/evidence-key.js.map +1 -0
- package/dist/src/retrieval/group-by-parent.d.ts +38 -0
- package/dist/src/retrieval/group-by-parent.d.ts.map +1 -0
- package/dist/src/retrieval/group-by-parent.js +40 -0
- package/dist/src/retrieval/group-by-parent.js.map +1 -0
- package/dist/src/retrieval/lexical.d.ts.map +1 -1
- package/dist/src/retrieval/lexical.js +1 -3
- package/dist/src/retrieval/lexical.js.map +1 -1
- package/dist/src/retrieval/receipt.d.ts +57 -0
- package/dist/src/retrieval/receipt.d.ts.map +1 -0
- package/dist/src/retrieval/receipt.js +119 -0
- package/dist/src/retrieval/receipt.js.map +1 -0
- package/dist/src/retrieval/reranker.d.ts +12 -2
- package/dist/src/retrieval/reranker.d.ts.map +1 -1
- package/dist/src/retrieval/reranker.js +11 -4
- package/dist/src/retrieval/reranker.js.map +1 -1
- package/dist/src/retrieval/stitch-chunks.d.ts +73 -0
- package/dist/src/retrieval/stitch-chunks.d.ts.map +1 -0
- package/dist/src/retrieval/stitch-chunks.js +106 -0
- package/dist/src/retrieval/stitch-chunks.js.map +1 -0
- package/dist/src/server/app.d.ts.map +1 -1
- package/dist/src/server/app.js +17 -1
- package/dist/src/server/app.js.map +1 -1
- package/dist/src/server/routes/conversations-search.d.ts.map +1 -1
- package/dist/src/server/routes/conversations-search.js +12 -3
- package/dist/src/server/routes/conversations-search.js.map +1 -1
- package/dist/src/server/routes/friend-status.d.ts +44 -5
- package/dist/src/server/routes/friend-status.d.ts.map +1 -1
- package/dist/src/server/routes/friend-status.js +74 -6
- package/dist/src/server/routes/friend-status.js.map +1 -1
- package/dist/src/server/routes/mcp-usage.d.ts +9 -6
- package/dist/src/server/routes/mcp-usage.d.ts.map +1 -1
- package/dist/src/server/routes/mcp-usage.js.map +1 -1
- package/dist/src/server/routes/retrieval-feedback.d.ts +3 -0
- package/dist/src/server/routes/retrieval-feedback.d.ts.map +1 -0
- package/dist/src/server/routes/retrieval-feedback.js +290 -0
- package/dist/src/server/routes/retrieval-feedback.js.map +1 -0
- package/dist/src/server/routes/save.d.ts +3 -3
- package/dist/src/server/routes/save.d.ts.map +1 -1
- package/dist/src/server/routes/save.js +6 -2
- package/dist/src/server/routes/save.js.map +1 -1
- package/dist/src/server/routes/search.d.ts.map +1 -1
- package/dist/src/server/routes/search.js +19 -7
- package/dist/src/server/routes/search.js.map +1 -1
- package/dist/src/server/serving-marker.d.ts +85 -0
- package/dist/src/server/serving-marker.d.ts.map +1 -0
- package/dist/src/server/serving-marker.js +226 -0
- package/dist/src/server/serving-marker.js.map +1 -0
- package/dist/src/storage/chunk-backfill.d.ts +39 -0
- package/dist/src/storage/chunk-backfill.d.ts.map +1 -0
- package/dist/src/storage/chunk-backfill.js +295 -0
- package/dist/src/storage/chunk-backfill.js.map +1 -0
- package/dist/src/storage/filter.d.ts +42 -0
- package/dist/src/storage/filter.d.ts.map +1 -0
- package/dist/src/storage/filter.js +70 -0
- package/dist/src/storage/filter.js.map +1 -0
- package/dist/src/storage/rebuild.d.ts.map +1 -1
- package/dist/src/storage/rebuild.js +44 -27
- package/dist/src/storage/rebuild.js.map +1 -1
- package/dist/src/storage/tables.d.ts +41 -0
- package/dist/src/storage/tables.d.ts.map +1 -1
- package/dist/src/storage/tables.js +64 -1
- package/dist/src/storage/tables.js.map +1 -1
- package/operator/swiftbar/render-menu.py +57 -15
- package/package.json +5 -3
|
@@ -34,10 +34,10 @@ import { sanitizeProjectLabel } from "../../runtime/legacy-name-guard.js";
|
|
|
34
34
|
import { validateVoyageKey } from "../../onboarding/voyage-validate.js";
|
|
35
35
|
import { writeEnvFile } from "../../onboarding/env-file.js";
|
|
36
36
|
import { kickstartDaemon, waitForHealth, } from "../../onboarding/daemon-control.js";
|
|
37
|
-
import { runAutoCapture, resolveCodexCaptureDeps, } from "../../capture/auto-capture.js";
|
|
37
|
+
import { runAutoCapture, resolveCodexCaptureDeps, resolveCursorCaptureDeps, } from "../../capture/auto-capture.js";
|
|
38
38
|
import { appendAutoCaptureRunRecord, buildAutoCaptureRunRecord, } from "../../capture/observability.js";
|
|
39
|
-
import { DEFAULT_AUTO_CAPTURE_SOURCES } from "../../capture/sources.js";
|
|
40
|
-
import {
|
|
39
|
+
import { DEFAULT_AUTO_CAPTURE_SOURCES, CURSOR_CAPTURE_SOURCE, } from "../../capture/sources.js";
|
|
40
|
+
import { createTriageProvider, resolveTriageProviderName, setConfiguredTriageProviderName, triageWorkerLabel, } from "../../capture/triage-provider-factory.js";
|
|
41
41
|
import { discoverClaudeCodeSessions } from "../../ingestion/parsers/claude-code-jsonl.js";
|
|
42
42
|
import { discoverCodexSessions } from "../../ingestion/parsers/codex-jsonl.js";
|
|
43
43
|
import { sniffInboxSource } from "../../ingestion/inbox-core/source-sniffer.js";
|
|
@@ -89,11 +89,12 @@ export function makeOnboardCommand() {
|
|
|
89
89
|
.option("--reconfigure-voyage", "Recovery flow: replace the Voyage key only", false)
|
|
90
90
|
.option("--yes", "Accept all defaults (non-interactive)", false)
|
|
91
91
|
.option("--skip-capture", "Skip the post-setup capture pass (test-only)", false)
|
|
92
|
-
.option("--no-codex-capture", "Skip the
|
|
92
|
+
.option("--no-codex-capture", "Skip the triage-worker preflight + disable the capture pass for this run")
|
|
93
93
|
.option("--with-claude-hook", "Install the Rift policy hook into Claude Code without prompting", false)
|
|
94
94
|
.option("--no-claude-hook", "Skip the Claude Code policy-hook prompt entirely")
|
|
95
95
|
.option("--enable-codex-enrichment", "Opt into Codex AI metadata enrichment (default: AI-free import + keyword search)", false)
|
|
96
|
-
.option("--enable-
|
|
96
|
+
.option("--enable-claude-enrichment", "Opt into Claude Code AI metadata enrichment (digests/compaction stay off until Claude digest support ships; mutually exclusive with --enable-codex-enrichment)", false)
|
|
97
|
+
.option("--enable-capture", "Opt into scheduled chat capture + its triage-worker preflight (Codex by default, or Claude Code via capture.triage.provider; default: capture off, zero AI-worker calls)", false)
|
|
97
98
|
.action(async (opts, cmd) => {
|
|
98
99
|
const globalOpts = cmd.optsWithGlobals();
|
|
99
100
|
try {
|
|
@@ -119,6 +120,13 @@ export async function runOnboard(opts, globalOpts) {
|
|
|
119
120
|
terminal: !!process.stdin.isTTY,
|
|
120
121
|
});
|
|
121
122
|
try {
|
|
123
|
+
// Fail fast, before any config write: the two enrichment opt-ins pick
|
|
124
|
+
// different metadata workers (Codex vs Claude), so passing both is an
|
|
125
|
+
// ambiguous request, not a mergeable one. Reject it up front rather than
|
|
126
|
+
// letting last-writer-wins silently decide which provider you got.
|
|
127
|
+
if (opts.enableCodexEnrichment === true && opts.enableClaudeEnrichment === true) {
|
|
128
|
+
throw new CliError("Pass only one of --enable-codex-enrichment or --enable-claude-enrichment — they select different metadata workers.", "validation");
|
|
129
|
+
}
|
|
122
130
|
if (opts.reconfigureVoyage) {
|
|
123
131
|
await reconfigureVoyageFlow(opts, globalOpts, rl);
|
|
124
132
|
return;
|
|
@@ -152,6 +160,7 @@ export async function runOnboard(opts, globalOpts) {
|
|
|
152
160
|
// AI-free import + keyword search (zero Codex calls). Only persisted when
|
|
153
161
|
// the user explicitly passed --enable-codex-enrichment.
|
|
154
162
|
applyCodexEnrichmentOptIn(opts.enableCodexEnrichment, globalOpts.config, say);
|
|
163
|
+
applyClaudeEnrichmentOptIn(opts.enableClaudeEnrichment, globalOpts.config, say);
|
|
155
164
|
// Step 2d — optional opt-in to scheduled chat capture. Default off, so a
|
|
156
165
|
// fresh install makes zero Codex calls. Auto-capture embeds each saved
|
|
157
166
|
// conversation, so it requires a Voyage key; opting in without one would
|
|
@@ -190,7 +199,7 @@ export async function runOnboard(opts, globalOpts) {
|
|
|
190
199
|
throw new CliError(`Voyage smoke failed after daemon kickstart: ${refresh.reason}`, "server_error");
|
|
191
200
|
}
|
|
192
201
|
}
|
|
193
|
-
// Step 3 —
|
|
202
|
+
// Step 3 — triage-worker preflight (capture lane only).
|
|
194
203
|
//
|
|
195
204
|
// Capture is OFF by default (trust-first): a fresh install makes zero
|
|
196
205
|
// Codex calls. The preflight below performs a real Codex triage call,
|
|
@@ -205,6 +214,27 @@ export async function runOnboard(opts, globalOpts) {
|
|
|
205
214
|
// `--no-codex-capture` skips the preflight even when capture was enabled
|
|
206
215
|
// (e.g. enable the daemon schedule but skip the one-shot).
|
|
207
216
|
let captureDisabled = false;
|
|
217
|
+
// `codexUnavailable` is set ONLY when capture was enabled and the live
|
|
218
|
+
// Codex preflight actually failed — i.e. scheduled capture is configured
|
|
219
|
+
// on but cannot run until Codex is fixed. `--no-codex-capture` is NOT this
|
|
220
|
+
// case: it only skips the onboarding one-shot, leaving the daemon's
|
|
221
|
+
// scheduled capture to run normally. Keeping the two apart is what lets the
|
|
222
|
+
// import-prompt and summary copy stay honest instead of either over- or
|
|
223
|
+
// under-promising automatic capture.
|
|
224
|
+
let codexUnavailable = false;
|
|
225
|
+
// Resolve the configured triage worker so the preflight probes (and labels)
|
|
226
|
+
// the worker the daemon will actually use, and record it process-wide so
|
|
227
|
+
// the first-capture pass below inherits the same selection. Unreadable
|
|
228
|
+
// config falls back to codex_cli — byte-for-byte the prior default.
|
|
229
|
+
let triageWorkerName = "codex_cli";
|
|
230
|
+
try {
|
|
231
|
+
triageWorkerName = resolveTriageProviderName(loadConfig(path.resolve(globalOpts.config)));
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
triageWorkerName = "codex_cli";
|
|
235
|
+
}
|
|
236
|
+
setConfiguredTriageProviderName(triageWorkerName);
|
|
237
|
+
const workerLabel = triageWorkerLabel(triageWorkerName);
|
|
208
238
|
if (!captureEnabled) {
|
|
209
239
|
ui.step("skip", "Chat access", captureRequested
|
|
210
240
|
? "capture needs a Voyage key — skipped"
|
|
@@ -216,21 +246,48 @@ export async function runOnboard(opts, globalOpts) {
|
|
|
216
246
|
captureDisabled = true;
|
|
217
247
|
}
|
|
218
248
|
else {
|
|
219
|
-
const
|
|
220
|
-
const
|
|
221
|
-
if (
|
|
222
|
-
|
|
249
|
+
const preflightSpin = new ui.Spinner("Chat access").start();
|
|
250
|
+
const preflightOk = await triagePreflight(triageWorkerName);
|
|
251
|
+
if (preflightOk) {
|
|
252
|
+
preflightSpin.succeed("Chat access", `ready · ${workerLabel}`);
|
|
223
253
|
}
|
|
224
254
|
else {
|
|
225
|
-
|
|
226
|
-
ui.note(
|
|
255
|
+
preflightSpin.fail("Chat access", `not ready · ${workerLabel} — auto-import off`);
|
|
256
|
+
ui.note(triageWorkerName === "claude_code"
|
|
257
|
+
? "To enable later: run `claude` once and sign in, then re-run `rift onboard`."
|
|
258
|
+
: "To enable later: run `codex login`, then re-run `rift onboard`.");
|
|
227
259
|
captureDisabled = true;
|
|
260
|
+
codexUnavailable = true;
|
|
228
261
|
}
|
|
229
262
|
}
|
|
263
|
+
// Will the daemon's scheduled auto-capture actually run going forward?
|
|
264
|
+
// Configured on (requested + Voyage key) AND Codex available. This is the
|
|
265
|
+
// signal the import prompt and the summary line must use — NOT bare
|
|
266
|
+
// `captureEnabled`, which is only "configured on" and stays true even after
|
|
267
|
+
// a failed Codex preflight already told the user auto-import is off.
|
|
268
|
+
const autoCaptureWillRun = captureEnabled && !codexUnavailable;
|
|
230
269
|
// Step 4 — discover sessions.
|
|
231
270
|
const claudeSessions = safeDiscover(() => discoverClaudeCodeSessions(path.join(os.homedir(), ".claude")));
|
|
232
271
|
const codexSessions = safeDiscover(() => discoverCodexSessions());
|
|
233
272
|
ui.step("ok", "Chat history", `${claudeSessions} Claude Code · ${codexSessions} Codex CLI`);
|
|
273
|
+
// Set the expectation honestly up front: auto-capture covers the CLI agents,
|
|
274
|
+
// not every AI app on the Mac. The Claude/ChatGPT desktop + web apps keep
|
|
275
|
+
// their history server-side, so those chats arrive via export → rift import.
|
|
276
|
+
// `ui.detail` (legible, not dimmed) because this is trust-critical copy.
|
|
277
|
+
//
|
|
278
|
+
// The CLI-agent line is gated on `autoCaptureWillRun`: "captured
|
|
279
|
+
// automatically" is only true once capture is enabled AND the worker
|
|
280
|
+
// preflight passed. On a default/off or not-ready install (we just printed
|
|
281
|
+
// "capture off"/"not ready" above) we describe ELIGIBILITY instead, so the
|
|
282
|
+
// block never contradicts the gate it sits under.
|
|
283
|
+
const cliAgentsLine = autoCaptureWillRun
|
|
284
|
+
? " • Claude Code + Codex CLI — captured automatically\n"
|
|
285
|
+
: " • Claude Code + Codex CLI — eligible for auto-capture once capture is enabled and chat access is ready\n";
|
|
286
|
+
ui.detail("Auto-capture covers your terminal AI agents — not every AI app on your Mac:\n" +
|
|
287
|
+
cliAgentsLine +
|
|
288
|
+
" • Cursor — only if you turn it on (add cursor_composer to capture.sources)\n" +
|
|
289
|
+
" • Claude Desktop / ChatGPT / web chats — NOT automatic; export them, then:\n" +
|
|
290
|
+
" rift import <file> --source claude_web (or chatgpt_web)");
|
|
234
291
|
// Step 5 — beta opt-in (stay connected: news, pricing, feedback).
|
|
235
292
|
const feedback = await collectFeedbackPreference(opts, dataDir, rl);
|
|
236
293
|
if (feedback.email) {
|
|
@@ -246,6 +303,7 @@ export async function runOnboard(opts, globalOpts) {
|
|
|
246
303
|
await maybeInstallClaudeCodeHook(opts, rl);
|
|
247
304
|
// Step 6 + 7 — watermark current sessions + run one capture pass.
|
|
248
305
|
let captureSaved = 0;
|
|
306
|
+
let captureRan = false;
|
|
249
307
|
if (opts.skipCapture) {
|
|
250
308
|
ui.step("skip", "Chat import", "skipped (--skip-capture)");
|
|
251
309
|
}
|
|
@@ -262,6 +320,7 @@ export async function runOnboard(opts, globalOpts) {
|
|
|
262
320
|
ui.step("skip", "Chat import", "skipped (capture not enabled)");
|
|
263
321
|
}
|
|
264
322
|
else {
|
|
323
|
+
captureRan = true;
|
|
265
324
|
const captureResult = await runFirstCapturePass(globalOpts.config, dataDir);
|
|
266
325
|
captureSaved = captureResult.saved;
|
|
267
326
|
// Per A-1.1/C-1.3: a token-issuance failure during capture-pass
|
|
@@ -275,12 +334,18 @@ export async function runOnboard(opts, globalOpts) {
|
|
|
275
334
|
}
|
|
276
335
|
// Step 8 — optional export import.
|
|
277
336
|
let importSucceeded = false;
|
|
337
|
+
let importAttempted = false;
|
|
278
338
|
if (isOff(opts, "importExport", "noImportExport")) {
|
|
279
339
|
ui.step("skip", "File import", "skipped (--no-import-export)");
|
|
280
340
|
}
|
|
281
341
|
else {
|
|
282
|
-
const importPath = await collectImportPath(opts, rl
|
|
342
|
+
const importPath = await collectImportPath(opts, rl, {
|
|
343
|
+
willRun: autoCaptureWillRun,
|
|
344
|
+
configured: captureEnabled,
|
|
345
|
+
workerLabel,
|
|
346
|
+
});
|
|
283
347
|
if (importPath) {
|
|
348
|
+
importAttempted = true;
|
|
284
349
|
const outcome = await runImport(importPath, globalOpts.config);
|
|
285
350
|
if (outcome.kind === "imported" || outcome.kind === "duplicate") {
|
|
286
351
|
importSucceeded = true;
|
|
@@ -291,30 +356,46 @@ export async function runOnboard(opts, globalOpts) {
|
|
|
291
356
|
}
|
|
292
357
|
}
|
|
293
358
|
// Step 9 — first-recall verification.
|
|
294
|
-
//
|
|
295
|
-
//
|
|
296
|
-
//
|
|
297
|
-
//
|
|
359
|
+
// A recall check only makes sense once this run actually landed user data.
|
|
360
|
+
// When nothing was imported or captured (the default, deliberate path), we
|
|
361
|
+
// skip the search check rather than start a spinner and FAIL it — failing a
|
|
362
|
+
// check the user opted out of is what made a clean setup feel broken.
|
|
298
363
|
const ingestedAny = captureSaved > 0 || importSucceeded;
|
|
299
|
-
const
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
recallSpin.succeed("Search check", `found ${recall.hits} result(s)`);
|
|
305
|
-
}
|
|
306
|
-
else if (recall.ok) {
|
|
307
|
-
// 0 hits is NOT success — decideOnboardOutcome treats it as incomplete.
|
|
308
|
-
recallSpin.warn("Search check", "no results yet — index is fresh, try a query shortly");
|
|
364
|
+
const ingestAttempted = captureRan || importAttempted;
|
|
365
|
+
let recall;
|
|
366
|
+
if (!ingestedAny) {
|
|
367
|
+
ui.step("skip", "Search check", "nothing imported yet — skipped");
|
|
368
|
+
recall = { ok: false, reason: "nothing imported yet" };
|
|
309
369
|
}
|
|
310
370
|
else {
|
|
311
|
-
recallSpin.
|
|
371
|
+
const recallSpin = new ui.Spinner("Search check").start();
|
|
372
|
+
recall = await firstRecallCheck(globalOpts.config);
|
|
373
|
+
if (recall.ok && recall.hits > 0) {
|
|
374
|
+
recallSpin.succeed("Search check", `found ${recall.hits} result(s)`);
|
|
375
|
+
}
|
|
376
|
+
else if (recall.ok) {
|
|
377
|
+
recallSpin.warn("Search check", "no results yet — index is fresh, try a query shortly");
|
|
378
|
+
}
|
|
379
|
+
else {
|
|
380
|
+
recallSpin.fail("Search check", recall.reason);
|
|
381
|
+
}
|
|
312
382
|
}
|
|
313
383
|
// Step 10 — next-action card.
|
|
314
|
-
const card = decideOnboardOutcome({ ingestedAny, recall });
|
|
384
|
+
const card = decideOnboardOutcome({ ingestedAny, recall, ingestAttempted });
|
|
315
385
|
card.push(ui.pc.dim(last4 !== null
|
|
316
386
|
? `Voyage: key valid (last 4 …${last4})${safeLabel ? ` · label ${safeLabel}` : ""}`
|
|
317
387
|
: "Search: keyword-only (no embedding key) — add one later for semantic search"));
|
|
388
|
+
// One-line "what's on/off" so the friend leaves knowing whether Rift keeps
|
|
389
|
+
// itself fed. Three honest states: ready (configured + worker available),
|
|
390
|
+
// configured-but-not-ready (preflight failed — don't claim it's running),
|
|
391
|
+
// and off (the default). Capture is off by default (zero-egress default).
|
|
392
|
+
card.push(ui.pc.dim(autoCaptureWillRun
|
|
393
|
+
? "Auto-capture: on — new chats are captured on a schedule."
|
|
394
|
+
: captureEnabled
|
|
395
|
+
? `Auto-capture: configured on, but not ready — ${workerLabel} isn't available (${triageWorkerName === "claude_code"
|
|
396
|
+
? "run `claude` and sign in"
|
|
397
|
+
: "run `codex login`"}).`
|
|
398
|
+
: "Auto-capture: off — enable with: rift onboard --enable-capture"));
|
|
318
399
|
ui.box(card);
|
|
319
400
|
ui.line("");
|
|
320
401
|
}
|
|
@@ -446,8 +527,10 @@ export function persistVoyageLabel(configPath, label) {
|
|
|
446
527
|
* Persist the Codex AI-metadata-enrichment opt-in into config.json. Default
|
|
447
528
|
* onboarding leaves `enrichment.ai_metadata = false` (AI-free import + keyword
|
|
448
529
|
* search, zero Codex calls). When the user passes `--enable-codex-enrichment`,
|
|
449
|
-
* this flips it to true
|
|
450
|
-
*
|
|
530
|
+
* this flips it to true AND pins `enrichment.metadata.provider = "codex_cli"` so
|
|
531
|
+
* the daemon/worker select the Codex-backed extractor — overriding any prior
|
|
532
|
+
* `claude_code` pin rather than silently leaving Claude selected. Backs the file
|
|
533
|
+
* up first, mirroring `persistVoyageLabel`.
|
|
451
534
|
*
|
|
452
535
|
* Exported for orchestrator-level tests; `runOnboard` is the only production
|
|
453
536
|
* caller. Returns true when the flag was set and persisted, false otherwise.
|
|
@@ -465,6 +548,55 @@ export function applyCodexEnrichmentOptIn(enable, configPath, emit) {
|
|
|
465
548
|
const parsed = JSON.parse(raw);
|
|
466
549
|
const enrichment = parsed["enrichment"] ?? {};
|
|
467
550
|
enrichment["ai_metadata"] = true;
|
|
551
|
+
// Pin the metadata worker to Codex explicitly. Setting only `ai_metadata`
|
|
552
|
+
// would leave a pre-existing `metadata.provider = "claude_code"` in place, so
|
|
553
|
+
// "use Codex" would silently keep routing metadata through Claude (and keep
|
|
554
|
+
// digests off). Codex opt-in must win the provider selection, not just the gate.
|
|
555
|
+
const metadata = enrichment["metadata"] ?? {};
|
|
556
|
+
metadata["provider"] = "codex_cli";
|
|
557
|
+
enrichment["metadata"] = metadata;
|
|
558
|
+
parsed["enrichment"] = enrichment;
|
|
559
|
+
const tmp = `${absolute}.tmp.${process.pid}`;
|
|
560
|
+
fs.writeFileSync(tmp, JSON.stringify(parsed, null, 2) + "\n", {
|
|
561
|
+
encoding: "utf8",
|
|
562
|
+
mode: 0o644,
|
|
563
|
+
});
|
|
564
|
+
fs.renameSync(tmp, absolute);
|
|
565
|
+
emit("Codex AI metadata enrichment enabled (enrichment.ai_metadata = true, metadata.provider = codex_cli).");
|
|
566
|
+
return true;
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* Persist the Claude-Code AI-metadata-enrichment opt-in into config.json. Like
|
|
570
|
+
* `applyCodexEnrichmentOptIn` it flips `enrichment.ai_metadata = true`, but it
|
|
571
|
+
* ALSO pins `enrichment.metadata.provider = "claude_code"` so the daemon/worker
|
|
572
|
+
* route metadata through the `claude` CLI instead of Codex. Backs the file up
|
|
573
|
+
* first, mirroring the Codex opt-in. Callers must reject the combination of
|
|
574
|
+
* both enrichment flags before reaching here (see `runOnboard`).
|
|
575
|
+
*
|
|
576
|
+
* Discloses the one capability this does NOT turn on: there is no Claude digest
|
|
577
|
+
* worker yet and we will not silently borrow Codex for it, so digests/
|
|
578
|
+
* compaction stay off until a dedicated digest-provider slice ships. Saying so
|
|
579
|
+
* here prevents a silent capability loss for a user who switches to Claude.
|
|
580
|
+
*
|
|
581
|
+
* Exported for orchestrator-level tests; `runOnboard` is the only production
|
|
582
|
+
* caller. Returns true when the flag was set and persisted, false otherwise.
|
|
583
|
+
*/
|
|
584
|
+
export function applyClaudeEnrichmentOptIn(enable, configPath, emit) {
|
|
585
|
+
if (enable !== true)
|
|
586
|
+
return false;
|
|
587
|
+
const absolute = path.resolve(configPath);
|
|
588
|
+
if (!fs.existsSync(absolute)) {
|
|
589
|
+
throw new CliError(`Cannot persist enrichment opt-in: config not found at ${absolute}`, "validation");
|
|
590
|
+
}
|
|
591
|
+
const raw = fs.readFileSync(absolute, "utf8");
|
|
592
|
+
const stamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
593
|
+
fs.writeFileSync(`${absolute}.bak.${stamp}`, raw, { encoding: "utf8", mode: 0o600 });
|
|
594
|
+
const parsed = JSON.parse(raw);
|
|
595
|
+
const enrichment = parsed["enrichment"] ?? {};
|
|
596
|
+
enrichment["ai_metadata"] = true;
|
|
597
|
+
const metadata = enrichment["metadata"] ?? {};
|
|
598
|
+
metadata["provider"] = "claude_code";
|
|
599
|
+
enrichment["metadata"] = metadata;
|
|
468
600
|
parsed["enrichment"] = enrichment;
|
|
469
601
|
const tmp = `${absolute}.tmp.${process.pid}`;
|
|
470
602
|
fs.writeFileSync(tmp, JSON.stringify(parsed, null, 2) + "\n", {
|
|
@@ -472,7 +604,7 @@ export function applyCodexEnrichmentOptIn(enable, configPath, emit) {
|
|
|
472
604
|
mode: 0o644,
|
|
473
605
|
});
|
|
474
606
|
fs.renameSync(tmp, absolute);
|
|
475
|
-
emit("
|
|
607
|
+
emit("Claude metadata enrichment enabled. Digests/compaction stay off until Claude digest support ships.");
|
|
476
608
|
return true;
|
|
477
609
|
}
|
|
478
610
|
/**
|
|
@@ -704,12 +836,18 @@ export function describeTokenFailure(reason) {
|
|
|
704
836
|
}
|
|
705
837
|
return "re-run `rift onboard`. If the failure repeats, run `rift feedback --kind=broke --with-status` to ship a diagnostic bundle.";
|
|
706
838
|
}
|
|
707
|
-
// ----- Step 3:
|
|
708
|
-
|
|
839
|
+
// ----- Step 3: triage-worker preflight -----
|
|
840
|
+
/**
|
|
841
|
+
* Live triage probe for the CONFIGURED worker (Codex CLI by default, or Claude
|
|
842
|
+
* Code when `capture.triage.provider = claude_code`). Routing through the
|
|
843
|
+
* factory — not a hardcoded CodexCliTriageProvider — is what stops a Claude
|
|
844
|
+
* Code user who deliberately picked `claude_code` from being failed by a Codex
|
|
845
|
+
* probe they never asked for.
|
|
846
|
+
*/
|
|
847
|
+
async function triagePreflight(name) {
|
|
709
848
|
try {
|
|
710
|
-
await
|
|
849
|
+
await createTriageProvider(name, { timeoutMs: 120_000 }).triage({
|
|
711
850
|
content: "User: Rift onboarding preflight.\n\nAssistant: Ready.",
|
|
712
|
-
source: "codex_cli",
|
|
713
851
|
});
|
|
714
852
|
return true;
|
|
715
853
|
}
|
|
@@ -763,7 +901,17 @@ export async function collectFeedbackPreference(opts, dataDir, rl, store = macRe
|
|
|
763
901
|
!opts.enableFeedbackRelay &&
|
|
764
902
|
!opts.yes &&
|
|
765
903
|
process.stdin.isTTY) {
|
|
766
|
-
|
|
904
|
+
// Most friends will NOT have an invite code — make that the obvious,
|
|
905
|
+
// pressure-free default so the bare prompt doesn't read as "something is
|
|
906
|
+
// missing". An invite only turns on the direct feedback relay; the email
|
|
907
|
+
// ask below (and `rift feedback`) work without it.
|
|
908
|
+
ui.detail([
|
|
909
|
+
"Feedback channel (optional)",
|
|
910
|
+
"• Have an invite code from Clem? Paste it to turn on the direct feedback relay.",
|
|
911
|
+
"• No code? Just press Enter — this is optional, and most people skip it.",
|
|
912
|
+
"• Either way you can send feedback any time with `rift feedback`.",
|
|
913
|
+
].join("\n"));
|
|
914
|
+
const pasted = (await ask(rl, "Invite code from Clem (or press Enter to skip): ")).trim();
|
|
767
915
|
if (pasted) {
|
|
768
916
|
try {
|
|
769
917
|
const invite = parseInvite(pasted);
|
|
@@ -1029,15 +1177,38 @@ export async function runFirstCapturePass(configPath, dataDir) {
|
|
|
1029
1177
|
const token = tokenResult.token;
|
|
1030
1178
|
const client = createHttpClient({ baseUrl, token });
|
|
1031
1179
|
let codexCaptureDeps = {};
|
|
1180
|
+
let cursorCaptureDeps = {};
|
|
1181
|
+
// Onboarding is a config-driven capture path, so it must honor the Cursor
|
|
1182
|
+
// opt-in exactly like the daemon: if `cursor_composer` is in
|
|
1183
|
+
// `config.capture.sources`, this first pass authorizes Cursor discovery +
|
|
1184
|
+
// persistence WITHOUT the env flags (which exist only for ad-hoc dogfood
|
|
1185
|
+
// runs). Without this, onboarding would record cursor_composer in its ledger
|
|
1186
|
+
// row yet runAutoCapture would treat Cursor as disabled — capturing nothing.
|
|
1187
|
+
let cursorConfigEnabled = false;
|
|
1032
1188
|
let enabledSources = DEFAULT_AUTO_CAPTURE_SOURCES;
|
|
1189
|
+
// Worker name for the honest preflight-failed warning below (defaults to the
|
|
1190
|
+
// codex_cli label until config resolves).
|
|
1191
|
+
let captureWorkerLabel = triageWorkerLabel("codex_cli");
|
|
1033
1192
|
try {
|
|
1034
1193
|
const { loadConfig } = await import("../../config/loader.js");
|
|
1035
1194
|
const cfg = loadConfig(configPath);
|
|
1195
|
+
// Route this first capture pass through the configured triage worker —
|
|
1196
|
+
// runAutoCapture builds its provider from the process-wide configured name,
|
|
1197
|
+
// so without this a claude_code user's onboarding pass would silently fall
|
|
1198
|
+
// back to Codex. (Step 3 already set it; re-assert here so this function is
|
|
1199
|
+
// correct independent of call order.)
|
|
1200
|
+
const captureWorkerName = resolveTriageProviderName(cfg);
|
|
1201
|
+
setConfiguredTriageProviderName(captureWorkerName);
|
|
1202
|
+
captureWorkerLabel = triageWorkerLabel(captureWorkerName);
|
|
1036
1203
|
codexCaptureDeps = resolveCodexCaptureDeps(cfg);
|
|
1204
|
+
cursorCaptureDeps = resolveCursorCaptureDeps(cfg);
|
|
1205
|
+
cursorConfigEnabled = cfg.capture.sources.includes(CURSOR_CAPTURE_SOURCE);
|
|
1037
1206
|
enabledSources = cfg.capture.sources;
|
|
1038
1207
|
}
|
|
1039
1208
|
catch {
|
|
1040
1209
|
codexCaptureDeps = {};
|
|
1210
|
+
cursorCaptureDeps = {};
|
|
1211
|
+
cursorConfigEnabled = false;
|
|
1041
1212
|
}
|
|
1042
1213
|
const startedAt = new Date();
|
|
1043
1214
|
const captureSpin = new ui.Spinner("Chat import").start();
|
|
@@ -1052,6 +1223,8 @@ export async function runFirstCapturePass(configPath, dataDir) {
|
|
|
1052
1223
|
// ledger that says one thing while capture did another.
|
|
1053
1224
|
sources: enabledSources,
|
|
1054
1225
|
...codexCaptureDeps,
|
|
1226
|
+
...cursorCaptureDeps,
|
|
1227
|
+
cursorConfigEnabled,
|
|
1055
1228
|
saveFn: async (saveOpts) => {
|
|
1056
1229
|
const { data } = await client.post("/save", {
|
|
1057
1230
|
source: saveOpts.source,
|
|
@@ -1094,12 +1267,12 @@ export async function runFirstCapturePass(configPath, dataDir) {
|
|
|
1094
1267
|
: String(observabilityErr)}\n`);
|
|
1095
1268
|
}
|
|
1096
1269
|
const base = `${report.saved} added · ${report.review} to review`;
|
|
1097
|
-
// A preflight failure (
|
|
1098
|
-
// so an `errors > 0` check alone would `succeed()` on a run where
|
|
1099
|
-
// never ran — telling a friend everything's fine when it isn't.
|
|
1100
|
-
// failed probe as a warning too, and surface why.
|
|
1270
|
+
// A preflight failure (triage-worker health probe) carries 0 per-session
|
|
1271
|
+
// errors, so an `errors > 0` check alone would `succeed()` on a run where
|
|
1272
|
+
// triage never ran — telling a friend everything's fine when it isn't.
|
|
1273
|
+
// Treat a failed probe as a warning too, and surface why.
|
|
1101
1274
|
if (!report.preflight_ok) {
|
|
1102
|
-
captureSpin.warn("Chat import", `${base} ·
|
|
1275
|
+
captureSpin.warn("Chat import", `${base} · ${captureWorkerLabel} preflight failed${report.preflight_error ? ` (${report.preflight_error})` : ""}`);
|
|
1103
1276
|
}
|
|
1104
1277
|
else if (report.errors > 0) {
|
|
1105
1278
|
captureSpin.warn("Chat import", `${base} · ${report.errors} error(s)`);
|
|
@@ -1115,7 +1288,7 @@ export async function runFirstCapturePass(configPath, dataDir) {
|
|
|
1115
1288
|
}
|
|
1116
1289
|
}
|
|
1117
1290
|
// ----- Step 8: import -----
|
|
1118
|
-
async function collectImportPath(opts, rl) {
|
|
1291
|
+
async function collectImportPath(opts, rl, capture) {
|
|
1119
1292
|
// opts.importExport is `string | false | undefined` — Commander writes
|
|
1120
1293
|
// `false` when `--no-import-export` was passed, but the caller already
|
|
1121
1294
|
// short-circuits in that case. Only a non-empty string is a real path.
|
|
@@ -1129,11 +1302,23 @@ async function collectImportPath(opts, rl) {
|
|
|
1129
1302
|
// user who has never exported a chat archive shouldn't hit a bare
|
|
1130
1303
|
// "Drop a path" prompt. The source-sniffer below still fail-fasts a
|
|
1131
1304
|
// non-ChatGPT export, but the friend learns the boundary earlier here.
|
|
1305
|
+
//
|
|
1306
|
+
// The "skipping is fine" reassurance MUST match what will actually happen.
|
|
1307
|
+
// Auto-capture is OFF by default, AND can be configured-on-but-not-running
|
|
1308
|
+
// when the triage-worker preflight failed — promising "new chats get captured
|
|
1309
|
+
// automatically" in either case is the exact trust break this flow removes.
|
|
1310
|
+
// Only promise it when capture will genuinely run; otherwise point at the
|
|
1311
|
+
// real next step (fix the triage worker if configured, or enable it if off).
|
|
1312
|
+
const whySkip = capture.willRun
|
|
1313
|
+
? "skipping is fine — new chats get captured automatically."
|
|
1314
|
+
: capture.configured
|
|
1315
|
+
? `skipping is fine — import later with \`rift import\` (auto-capture is on but won't run until ${capture.workerLabel} is ready — see above).`
|
|
1316
|
+
: "skipping is fine — import later with `rift import`, or turn on auto-capture with `rift onboard --enable-capture`.";
|
|
1132
1317
|
ui.detail([
|
|
1133
1318
|
"Import past chats (optional)",
|
|
1134
1319
|
"• What: the file path to a ChatGPT data export (a .zip or .json on your Mac), e.g. ~/Downloads/chatgpt-export.zip.",
|
|
1135
1320
|
"• Where: chatgpt.com → Settings → Data controls → Export data, then unzip nothing — just drop the downloaded file's path here.",
|
|
1136
|
-
|
|
1321
|
+
`• Why: this seeds Rift with your existing ChatGPT history so search works on day one; ${whySkip}`,
|
|
1137
1322
|
"• Other tools: Claude/Grok/Gemini exports aren't imported here. Run them later with: rift import <path> --source claude_web|grok_web|gemini_web",
|
|
1138
1323
|
].join("\n"));
|
|
1139
1324
|
const answer = (await ask(rl, "Path to a ChatGPT export to import now (or `skip`): ", "skip")).trim();
|
|
@@ -1196,14 +1381,22 @@ async function runImport(filePath, configPath) {
|
|
|
1196
1381
|
return { kind: "imported", jobId: resp.job_id };
|
|
1197
1382
|
}
|
|
1198
1383
|
/**
|
|
1199
|
-
* Pure outcome decision for the next-action card.
|
|
1200
|
-
*
|
|
1201
|
-
*
|
|
1202
|
-
*
|
|
1203
|
-
* user data, not a leftover probe.
|
|
1384
|
+
* Pure outcome decision for the next-action card.
|
|
1385
|
+
*
|
|
1386
|
+
* "Complete + verified" needs both: this run ingested user data AND a recall
|
|
1387
|
+
* query returned a hit (smoke is non-indexing — see daemonRefreshFlow — so a
|
|
1388
|
+
* hit is real user data, not a leftover probe).
|
|
1389
|
+
*
|
|
1390
|
+
* But an EMPTY archive is not a failure. By default capture is OFF (zero-Codex
|
|
1391
|
+
* trust default) and import is optional, so a friend who simply presses Enter
|
|
1392
|
+
* past the import prompt has finished a valid setup — they just have nothing to
|
|
1393
|
+
* recall yet. That case (`ingestAttempted === false`) is reported as DONE, not
|
|
1394
|
+
* "incomplete". We only flag a retry when an ingest was actually attempted and
|
|
1395
|
+
* still added nothing.
|
|
1204
1396
|
*/
|
|
1205
1397
|
export function decideOnboardOutcome(input) {
|
|
1206
1398
|
const { ingestedAny, recall } = input;
|
|
1399
|
+
const ingestAttempted = input.ingestAttempted ?? false;
|
|
1207
1400
|
if (ingestedAny && recall.ok && recall.hits > 0) {
|
|
1208
1401
|
return [
|
|
1209
1402
|
`Setup complete — recall returned ${recall.hits} result(s) from your data.`,
|
|
@@ -1211,10 +1404,19 @@ export function decideOnboardOutcome(input) {
|
|
|
1211
1404
|
];
|
|
1212
1405
|
}
|
|
1213
1406
|
if (!ingestedAny) {
|
|
1407
|
+
if (!ingestAttempted) {
|
|
1408
|
+
// Deliberate empty setup — a finished, valid state, not a failure.
|
|
1409
|
+
return [
|
|
1410
|
+
"Setup complete — nothing imported yet.",
|
|
1411
|
+
"Import later: rift import <path> --source <name>",
|
|
1412
|
+
"Next: rift mcp install --client=claude-desktop",
|
|
1413
|
+
];
|
|
1414
|
+
}
|
|
1415
|
+
// An ingest ran but landed nothing — honest, calm retry guidance.
|
|
1214
1416
|
return [
|
|
1215
|
-
"Setup
|
|
1216
|
-
"
|
|
1217
|
-
"
|
|
1417
|
+
"Setup ready — but capture/import added nothing this run.",
|
|
1418
|
+
"Try: rift import <path> --source <name>",
|
|
1419
|
+
"If it repeats: rift feedback --kind=broke --with-status",
|
|
1218
1420
|
];
|
|
1219
1421
|
}
|
|
1220
1422
|
if (recall.ok) {
|
|
@@ -1377,7 +1579,8 @@ function say(line) {
|
|
|
1377
1579
|
function sayPrivacyContract() {
|
|
1378
1580
|
ui.detail([
|
|
1379
1581
|
"• Conversation content stays local (LanceDB + raw transcripts).",
|
|
1380
|
-
"•
|
|
1582
|
+
"• Indexed conversation text — and your search queries — leave the machine",
|
|
1583
|
+
" for embedding only when a Voyage key is configured (Voyage AI).",
|
|
1381
1584
|
"• The Voyage key sits in ~/.rift.env (mode 0600), is sent only to Voyage,",
|
|
1382
1585
|
" and is never logged or sent to Clem.",
|
|
1383
1586
|
"• Feedback is stored locally as JSONL. Relay is opt-in: explicit notes only,",
|