@getrift/rift 0.1.0-beta.21 → 0.1.0-beta.23
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/recover-quarantine.d.ts +4 -4
- 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 +79 -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 +3 -1
- package/dist/src/cli/commands/menubar.d.ts.map +1 -1
- package/dist/src/cli/commands/menubar.js +36 -12
- package/dist/src/cli/commands/menubar.js.map +1 -1
- package/dist/src/cli/commands/onboard.d.ts +22 -2
- package/dist/src/cli/commands/onboard.d.ts.map +1 -1
- package/dist/src/cli/commands/onboard.js +160 -32
- 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 +12 -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 +166 -1
- 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 +20 -13
- package/dist/src/cli/postinstall-menubar.d.ts.map +1 -1
- package/dist/src/cli/postinstall-menubar.js +56 -1
- package/dist/src/cli/postinstall-menubar.js.map +1 -1
- package/dist/src/cli/status/friend-header.d.ts +16 -3
- package/dist/src/cli/status/friend-header.d.ts.map +1 -1
- package/dist/src/cli/status/friend-header.js +186 -10
- package/dist/src/cli/status/friend-header.js.map +1 -1
- package/dist/src/cli/status/local-signals.d.ts +42 -4
- package/dist/src/cli/status/local-signals.d.ts.map +1 -1
- package/dist/src/cli/status/local-signals.js +52 -1
- 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 +35 -0
- package/dist/src/diagnostics/claude-preflight.d.ts.map +1 -0
- package/dist/src/diagnostics/claude-preflight.js +90 -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 +24 -0
- package/dist/src/diagnostics/codex-preflight.js.map +1 -1
- package/dist/src/diagnostics/doctor.d.ts +7 -4
- package/dist/src/diagnostics/doctor.d.ts.map +1 -1
- package/dist/src/diagnostics/doctor.js +70 -11
- package/dist/src/diagnostics/doctor.js.map +1 -1
- package/dist/src/diagnostics/memory-coverage.d.ts +54 -0
- package/dist/src/diagnostics/memory-coverage.d.ts.map +1 -0
- package/dist/src/diagnostics/memory-coverage.js +272 -0
- package/dist/src/diagnostics/memory-coverage.js.map +1 -0
- package/dist/src/diagnostics/notify.d.ts +20 -3
- package/dist/src/diagnostics/notify.d.ts.map +1 -1
- package/dist/src/diagnostics/notify.js +54 -14
- package/dist/src/diagnostics/notify.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 +27 -16
- package/dist/src/main.js.map +1 -1
- package/dist/src/mcp/capture-diagnostics.d.ts +51 -0
- package/dist/src/mcp/capture-diagnostics.d.ts.map +1 -0
- package/dist/src/mcp/capture-diagnostics.js +127 -0
- package/dist/src/mcp/capture-diagnostics.js.map +1 -0
- package/dist/src/mcp/memory-diagnostics.d.ts +6 -0
- package/dist/src/mcp/memory-diagnostics.d.ts.map +1 -0
- package/dist/src/mcp/memory-diagnostics.js +51 -0
- package/dist/src/mcp/memory-diagnostics.js.map +1 -0
- 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/mcp/tools/status.d.ts +15 -1
- package/dist/src/mcp/tools/status.d.ts.map +1 -1
- package/dist/src/mcp/tools/status.js +53 -2
- package/dist/src/mcp/tools/status.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/canonical-files.d.ts +48 -0
- package/dist/src/retrieval/canonical-files.d.ts.map +1 -0
- package/dist/src/retrieval/canonical-files.js +210 -0
- package/dist/src/retrieval/canonical-files.js.map +1 -0
- package/dist/src/retrieval/compact.d.ts +95 -0
- package/dist/src/retrieval/compact.d.ts.map +1 -1
- package/dist/src/retrieval/compact.js +254 -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 +65 -15
- package/dist/src/retrieval/context-pack.js.map +1 -1
- package/dist/src/retrieval/conversation-dedup.d.ts +40 -0
- package/dist/src/retrieval/conversation-dedup.d.ts.map +1 -0
- package/dist/src/retrieval/conversation-dedup.js +141 -0
- package/dist/src/retrieval/conversation-dedup.js.map +1 -0
- 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/feedback-ranking.d.ts +49 -0
- package/dist/src/retrieval/feedback-ranking.d.ts.map +1 -0
- package/dist/src/retrieval/feedback-ranking.js +138 -0
- package/dist/src/retrieval/feedback-ranking.js.map +1 -0
- package/dist/src/retrieval/git-state.d.ts +9 -0
- package/dist/src/retrieval/git-state.d.ts.map +1 -1
- package/dist/src/retrieval/git-state.js +18 -0
- package/dist/src/retrieval/git-state.js.map +1 -1
- 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 +49 -2
- package/dist/src/retrieval/reranker.d.ts.map +1 -1
- package/dist/src/retrieval/reranker.js +64 -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 +1 -1
- package/dist/src/server/app.d.ts.map +1 -1
- package/dist/src/server/app.js +20 -3
- 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 +22 -3
- package/dist/src/server/routes/conversations-search.js.map +1 -1
- package/dist/src/server/routes/friend-status.d.ts +64 -6
- package/dist/src/server/routes/friend-status.d.ts.map +1 -1
- package/dist/src/server/routes/friend-status.js +114 -18
- 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 +1 -1
- package/dist/src/server/routes/search.d.ts.map +1 -1
- package/dist/src/server/routes/search.js +55 -8
- 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 +60 -18
- package/package.json +6 -4
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory coverage diagnostics for status surfaces.
|
|
3
|
+
*
|
|
4
|
+
* Counts alone are not enough: "0 digests" can mean AI enrichment is off,
|
|
5
|
+
* Claude was selected (no digest worker yet), or compaction simply has not run.
|
|
6
|
+
* "0 structured docs" can mean no sources, empty sources, missing embeddings,
|
|
7
|
+
* or a watch-mode backfill gap. This module turns config + cheap filesystem
|
|
8
|
+
* probes + table counts into explicit, leak-safe reasons.
|
|
9
|
+
*/
|
|
10
|
+
import fs from "node:fs";
|
|
11
|
+
import path from "node:path";
|
|
12
|
+
import { buildIgnoredPaths } from "../ingestion/ignored-paths.js";
|
|
13
|
+
import { isSupported } from "../ingestion/extractor.js";
|
|
14
|
+
import { isWatcherPathIgnored } from "../ingestion/watcher.js";
|
|
15
|
+
const DEFAULT_SUPPORTED_FILE_SCAN_LIMIT = 100;
|
|
16
|
+
const DEFAULT_SOURCE_ENTRY_SCAN_LIMIT = 1_000;
|
|
17
|
+
export function buildMemoryCoverageDiagnostics(input) {
|
|
18
|
+
const counts = input.counts
|
|
19
|
+
? {
|
|
20
|
+
conversations: input.counts.conversations_hot + input.counts.conversations_cold,
|
|
21
|
+
digests: input.counts.digests,
|
|
22
|
+
structured_docs: input.counts.structured_docs,
|
|
23
|
+
}
|
|
24
|
+
: null;
|
|
25
|
+
return {
|
|
26
|
+
counts,
|
|
27
|
+
digests: buildDigestCoverage({
|
|
28
|
+
config: input.config,
|
|
29
|
+
counts,
|
|
30
|
+
compactAvailable: input.compactAvailable,
|
|
31
|
+
}),
|
|
32
|
+
documents: buildDocumentCoverage({
|
|
33
|
+
config: input.config,
|
|
34
|
+
counts,
|
|
35
|
+
voyageKeyPresent: input.voyageKeyPresent,
|
|
36
|
+
supportedFileScanLimit: input.supportedFileScanLimit ?? DEFAULT_SUPPORTED_FILE_SCAN_LIMIT,
|
|
37
|
+
}),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function selectedMetadataProvider(config) {
|
|
41
|
+
if (config.local_generation?.enabled === true)
|
|
42
|
+
return "ollama";
|
|
43
|
+
if (config.enrichment?.ai_metadata !== true)
|
|
44
|
+
return "basic";
|
|
45
|
+
return config.enrichment.metadata?.provider ?? "codex_cli";
|
|
46
|
+
}
|
|
47
|
+
function buildDigestCoverage(input) {
|
|
48
|
+
const provider = selectedMetadataProvider(input.config);
|
|
49
|
+
if (!input.counts) {
|
|
50
|
+
return {
|
|
51
|
+
status: "unknown",
|
|
52
|
+
metadata_provider: provider,
|
|
53
|
+
compact_available: input.compactAvailable,
|
|
54
|
+
summary: "Digest coverage could not be counted.",
|
|
55
|
+
next_action: "Run: rift status --json",
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
if (input.counts.digests > 0) {
|
|
59
|
+
return {
|
|
60
|
+
status: "indexed",
|
|
61
|
+
metadata_provider: provider,
|
|
62
|
+
compact_available: input.compactAvailable,
|
|
63
|
+
summary: `${input.counts.digests} digest${input.counts.digests === 1 ? "" : "s"} indexed.`,
|
|
64
|
+
next_action: null,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
if (provider === "basic") {
|
|
68
|
+
return {
|
|
69
|
+
status: "unavailable_basic",
|
|
70
|
+
metadata_provider: provider,
|
|
71
|
+
compact_available: input.compactAvailable,
|
|
72
|
+
summary: "No digests because AI enrichment is off, so no digest worker is registered.",
|
|
73
|
+
next_action: "Enable a digest worker, e.g. rift onboard --enable-codex-enrichment, then run rift compact.",
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
if (provider === "claude_code") {
|
|
77
|
+
return {
|
|
78
|
+
status: "unavailable_claude",
|
|
79
|
+
metadata_provider: provider,
|
|
80
|
+
compact_available: input.compactAvailable,
|
|
81
|
+
summary: "No digests because Claude Code metadata is selected, but Claude digest support has not shipped yet.",
|
|
82
|
+
next_action: "Use Codex or Ollama for digest generation for now; keep Claude metadata if you do not need digests.",
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
if (!input.compactAvailable) {
|
|
86
|
+
return {
|
|
87
|
+
status: "unavailable_worker",
|
|
88
|
+
metadata_provider: provider,
|
|
89
|
+
compact_available: input.compactAvailable,
|
|
90
|
+
summary: "No digests because the compact/digest worker is not available in this daemon.",
|
|
91
|
+
next_action: "Run: rift doctor",
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
// We know only that a digest-capable worker is registered and the digest
|
|
95
|
+
// count is zero — NOT that compaction never ran. A corpus younger than the
|
|
96
|
+
// compaction age threshold legitimately has a working worker, compaction
|
|
97
|
+
// having run repeatedly, and still zero digests. Stay honest about that.
|
|
98
|
+
return {
|
|
99
|
+
status: "available_not_run",
|
|
100
|
+
metadata_provider: provider,
|
|
101
|
+
compact_available: input.compactAvailable,
|
|
102
|
+
summary: "No digests yet. A digest worker is available, but nothing has been compacted into a digest — either no conversation has reached the compaction age threshold, or compaction has not run.",
|
|
103
|
+
next_action: "Run: rift compact --dry-run to see what would be compacted.",
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function buildDocumentCoverage(input) {
|
|
107
|
+
const sources = input.config.sources ?? [];
|
|
108
|
+
// Config-derived fields only (no filesystem touch). The probe-derived fields
|
|
109
|
+
// stay zeroed and `probed` stays false until we actually walk the sources.
|
|
110
|
+
const configDerived = {
|
|
111
|
+
probed: false,
|
|
112
|
+
configured_sources: sources.length,
|
|
113
|
+
existing_sources: 0,
|
|
114
|
+
cloud_sources: sources.filter((s) => s.extraction === "cloud").length,
|
|
115
|
+
local_sources: sources.filter((s) => s.extraction === "local").length,
|
|
116
|
+
sources_with_supported_files: 0,
|
|
117
|
+
supported_files_seen: 0,
|
|
118
|
+
cloud_supported_files_seen: 0,
|
|
119
|
+
local_supported_files_seen: 0,
|
|
120
|
+
scan_limit: input.supportedFileScanLimit,
|
|
121
|
+
scan_limited: false,
|
|
122
|
+
cloud_embedding_ready: input.voyageKeyPresent,
|
|
123
|
+
};
|
|
124
|
+
// Counts unavailable: nothing to conclude, and probing can't diagnose without
|
|
125
|
+
// a baseline count. Degrade to "unknown" without touching the filesystem.
|
|
126
|
+
if (!input.counts) {
|
|
127
|
+
return {
|
|
128
|
+
...configDerived,
|
|
129
|
+
status: "unknown",
|
|
130
|
+
summary: "Structured-document coverage could not be counted.",
|
|
131
|
+
next_action: "Run: rift status --json",
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
// Healthy steady state: documents are already indexed, so we owe no
|
|
135
|
+
// explanation and skip the probe entirely. `rift status --json` is polled
|
|
136
|
+
// ~every 10s by the menu bar; walking every configured source tree on each
|
|
137
|
+
// poll once docs exist is pure waste — the probe only earns its cost when
|
|
138
|
+
// docs == 0.
|
|
139
|
+
if (input.counts.structured_docs > 0) {
|
|
140
|
+
return {
|
|
141
|
+
...configDerived,
|
|
142
|
+
status: "indexed",
|
|
143
|
+
summary: `${input.counts.structured_docs} structured document${input.counts.structured_docs === 1 ? "" : "s"} indexed.`,
|
|
144
|
+
next_action: null,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
// Zero docs: probe the sources to explain why.
|
|
148
|
+
const probes = sources.map((source) => probeSource(source, input.config, input.supportedFileScanLimit));
|
|
149
|
+
const existingSources = probes.filter((p) => p.exists).length;
|
|
150
|
+
const supportedFilesSeen = sum(probes.map((p) => p.supportedFilesSeen));
|
|
151
|
+
const scanLimited = probes.some((p) => p.scanLimited);
|
|
152
|
+
const sourcesWithSupportedFiles = probes.filter((p) => p.supportedFilesSeen > 0).length;
|
|
153
|
+
const cloudSupportedFilesSeen = sum(probes.map((p, i) => sources[i]?.extraction === "cloud" ? p.supportedFilesSeen : 0));
|
|
154
|
+
const localSupportedFilesSeen = sum(probes.map((p, i) => sources[i]?.extraction === "local" ? p.supportedFilesSeen : 0));
|
|
155
|
+
const base = {
|
|
156
|
+
...configDerived,
|
|
157
|
+
probed: true,
|
|
158
|
+
existing_sources: existingSources,
|
|
159
|
+
sources_with_supported_files: sourcesWithSupportedFiles,
|
|
160
|
+
supported_files_seen: supportedFilesSeen,
|
|
161
|
+
cloud_supported_files_seen: cloudSupportedFilesSeen,
|
|
162
|
+
local_supported_files_seen: localSupportedFilesSeen,
|
|
163
|
+
scan_limited: scanLimited,
|
|
164
|
+
};
|
|
165
|
+
if (configDerived.configured_sources === 0) {
|
|
166
|
+
return {
|
|
167
|
+
...base,
|
|
168
|
+
status: "not_configured",
|
|
169
|
+
summary: "No structured documents because no document sources are configured.",
|
|
170
|
+
next_action: "Add a source to the active Rift config, then run rift reconcile.",
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
if (existingSources === 0) {
|
|
174
|
+
return {
|
|
175
|
+
...base,
|
|
176
|
+
status: "source_missing",
|
|
177
|
+
summary: "No structured documents because the configured source paths are missing on disk.",
|
|
178
|
+
next_action: "Fix or remove the missing source paths in the active Rift config.",
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
if (supportedFilesSeen === 0 && scanLimited) {
|
|
182
|
+
return {
|
|
183
|
+
...base,
|
|
184
|
+
status: "unknown",
|
|
185
|
+
summary: "No structured documents, and the source probe hit its scan limit before finding supported files.",
|
|
186
|
+
next_action: "Run: rift reconcile",
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
if (supportedFilesSeen === 0) {
|
|
190
|
+
return {
|
|
191
|
+
...base,
|
|
192
|
+
status: "source_empty",
|
|
193
|
+
summary: "No structured documents because the active sources contain no supported files.",
|
|
194
|
+
next_action: "Add supported files to an active source, or point the active config at the folders you want indexed.",
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
if (cloudSupportedFilesSeen > 0 && !input.voyageKeyPresent) {
|
|
198
|
+
return {
|
|
199
|
+
...base,
|
|
200
|
+
status: "embedding_unavailable",
|
|
201
|
+
summary: "No structured documents because cloud sources contain supported files, but no Voyage key is loaded.",
|
|
202
|
+
next_action: "Run: rift onboard --reconfigure-voyage",
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
...base,
|
|
207
|
+
status: "backfill_needed",
|
|
208
|
+
summary: "No structured documents even though active sources contain supported files; existing files likely need a reconcile/backfill pass.",
|
|
209
|
+
next_action: "Run: rift reconcile",
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
function probeSource(source, config, limit) {
|
|
213
|
+
let stat;
|
|
214
|
+
try {
|
|
215
|
+
stat = fs.statSync(source.path);
|
|
216
|
+
}
|
|
217
|
+
catch {
|
|
218
|
+
return { exists: false, supportedFilesSeen: 0, scanLimited: false };
|
|
219
|
+
}
|
|
220
|
+
if (!stat.isDirectory()) {
|
|
221
|
+
return { exists: false, supportedFilesSeen: 0, scanLimited: false };
|
|
222
|
+
}
|
|
223
|
+
const ignoredPaths = buildIgnoredPaths(source, config.data_paths);
|
|
224
|
+
const result = countSupportedFiles(source.path, ignoredPaths, limit, DEFAULT_SOURCE_ENTRY_SCAN_LIMIT);
|
|
225
|
+
return {
|
|
226
|
+
exists: true,
|
|
227
|
+
supportedFilesSeen: result.count,
|
|
228
|
+
scanLimited: result.limited,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
function countSupportedFiles(dir, ignoredPaths, supportedFileLimit, entryLimit) {
|
|
232
|
+
let count = 0;
|
|
233
|
+
let entriesSeen = 0;
|
|
234
|
+
let limited = false;
|
|
235
|
+
const visit = (current) => {
|
|
236
|
+
if (count >= supportedFileLimit || entriesSeen >= entryLimit) {
|
|
237
|
+
limited = true;
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
if (isWatcherPathIgnored(current, ignoredPaths))
|
|
241
|
+
return;
|
|
242
|
+
let entries;
|
|
243
|
+
try {
|
|
244
|
+
entries = fs.readdirSync(current, { withFileTypes: true });
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
for (const entry of entries) {
|
|
250
|
+
if (count >= supportedFileLimit || entriesSeen >= entryLimit) {
|
|
251
|
+
limited = true;
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
entriesSeen++;
|
|
255
|
+
const fullPath = path.join(current, entry.name);
|
|
256
|
+
if (isWatcherPathIgnored(fullPath, ignoredPaths))
|
|
257
|
+
continue;
|
|
258
|
+
if (entry.isDirectory() && !entry.isSymbolicLink()) {
|
|
259
|
+
visit(fullPath);
|
|
260
|
+
}
|
|
261
|
+
else if (entry.isFile() && isSupported(fullPath)) {
|
|
262
|
+
count++;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
};
|
|
266
|
+
visit(dir);
|
|
267
|
+
return { count, limited };
|
|
268
|
+
}
|
|
269
|
+
function sum(values) {
|
|
270
|
+
return values.reduce((acc, n) => acc + n, 0);
|
|
271
|
+
}
|
|
272
|
+
//# sourceMappingURL=memory-coverage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-coverage.js","sourceRoot":"","sources":["../../../src/diagnostics/memory-coverage.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
import type { DoctorIssue, DoctorIssueKind } from "./doctor.js";
|
|
2
2
|
/** Re-notify cadence for an issue that stays unresolved. */
|
|
3
3
|
export declare const RENOTIFY_INTERVAL_MS: number;
|
|
4
|
+
/**
|
|
5
|
+
* The only issue kinds that ever raise a friend-facing macOS banner — the
|
|
6
|
+
* user-ACTIONABLE failures, where the friend can sign in or add a key and the
|
|
7
|
+
* problem clears. Everything else (a transient codex/claude probe failure, an
|
|
8
|
+
* index-write or save error, a backend timeout) is operator-only: surfaced in
|
|
9
|
+
* `rift doctor` / `rift status` and the logs, never a banner, because a
|
|
10
|
+
* non-technical friend cannot act on it and Rift retries it on its own.
|
|
11
|
+
*
|
|
12
|
+
* New kinds default to operator-only (fail-closed): add a kind here only when
|
|
13
|
+
* there is a safe, concrete action the friend can take.
|
|
14
|
+
*/
|
|
15
|
+
export declare const FRIEND_NOTIFY_KINDS: ReadonlySet<DoctorIssueKind>;
|
|
4
16
|
export interface NotificationPayload {
|
|
5
17
|
/** macOS notification title — always the same friend-facing banner. */
|
|
6
18
|
title: string;
|
|
@@ -53,9 +65,14 @@ export declare function buildNotificationPayload(issue: DoctorIssue): Notificati
|
|
|
53
65
|
* Decide which notifications to send this tick and what state to persist.
|
|
54
66
|
* Pure: no IO, no clock except the injected `now`.
|
|
55
67
|
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
68
|
+
* Eligible issues are the intersection of `daemonObservable` (the daemon can
|
|
69
|
+
* see them) and `FRIEND_NOTIFY_KINDS` (the friend can act on them) — so a
|
|
70
|
+
* transient probe/index/save failure never reaches a banner.
|
|
71
|
+
*
|
|
72
|
+
* The dedup memory survives a healthy run: a record is retained until its 24h
|
|
73
|
+
* cooldown elapses, even on ticks where the issue is absent. That is the flood
|
|
74
|
+
* fix — without it, one healthy poll wiped the "already warned you" memory and
|
|
75
|
+
* the next recurrence re-notified, defeating the daily limit.
|
|
59
76
|
*/
|
|
60
77
|
export declare function planNotifications(input: PlanNotificationsInput): PlanNotificationsResult;
|
|
61
78
|
/** Absolute path to the dedup-state file under the data dir. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notify.d.ts","sourceRoot":"","sources":["../../../src/diagnostics/notify.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"notify.d.ts","sourceRoot":"","sources":["../../../src/diagnostics/notify.ts"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEhE,4DAA4D;AAC5D,eAAO,MAAM,oBAAoB,QAAsB,CAAC;AAExD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,mBAAmB,EAAE,WAAW,CAAC,eAAe,CAQ3D,CAAC;AAEH,MAAM,WAAW,mBAAmB;IAClC,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAC;IACd,sDAAsD;IACtD,QAAQ,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,kCAAkC;AAClC,MAAM,WAAW,YAAY;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,YAAY,CAAC,CAAC,CAAC;CACxD;AAOD,MAAM,WAAW,sBAAsB;IACrC,iEAAiE;IACjE,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,wCAAwC;IACxC,KAAK,EAAE,WAAW,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,uBAAuB;IACtC,kEAAkE;IAClE,aAAa,EAAE,mBAAmB,EAAE,CAAC;IACrC,sCAAsC;IACtC,SAAS,EAAE,WAAW,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,WAAW,GACjB,mBAAmB,CAMrB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,sBAAsB,GAC5B,uBAAuB,CA2DzB;AAED,gEAAgE;AAChE,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,uEAAuE;AACvE,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,CAW5D;AAED,2DAA2D;AAC3D,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,CAQ1E;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,mBAAmB,EAC5B,IAAI,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAA;CAAO,GACxC,IAAI,CAcN;AAED,iEAAiE;AACjE,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,WAAW,EAAE,EACrB,IAAI,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAA;CAAO,GACtD,IAAI,CAmBN"}
|
|
@@ -11,10 +11,15 @@
|
|
|
11
11
|
* about itself. That needs a separate watchdog and is explicitly Slice D
|
|
12
12
|
* (see docs/feedback/2026-05-20-friend-onboarding-status-surface.md).
|
|
13
13
|
*
|
|
14
|
-
* Rate-limiting rules (
|
|
14
|
+
* Rate-limiting rules (status-surface plan + the 2026-06 flood fix):
|
|
15
|
+
* - Only user-ACTIONABLE kinds (FRIEND_NOTIFY_KINDS) ever reach a friend;
|
|
16
|
+
* transient/infra failures (probe timeouts, index/save errors) are
|
|
17
|
+
* operator-only — visible in `rift doctor`/`status`, never a banner.
|
|
15
18
|
* - Notify on state transition, not every poll.
|
|
16
|
-
* - Do not repeat the same unresolved issue more than once per day
|
|
17
|
-
*
|
|
19
|
+
* - Do not repeat the same unresolved issue more than once per day — and the
|
|
20
|
+
* dedup memory SURVIVES a healthy run, so an intermittent failure
|
|
21
|
+
* (fail → heal → fail within 24h) notifies once, not on every recurrence.
|
|
22
|
+
* - After the cooldown elapses, a genuine later recurrence notifies fresh.
|
|
18
23
|
*
|
|
19
24
|
* The planning logic (`planNotifications`) is pure and fully tested; the
|
|
20
25
|
* IO (reading/writing dedup state, sending via osascript) is thin and
|
|
@@ -25,6 +30,26 @@ import fs from "node:fs";
|
|
|
25
30
|
import path from "node:path";
|
|
26
31
|
/** Re-notify cadence for an issue that stays unresolved. */
|
|
27
32
|
export const RENOTIFY_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
33
|
+
/**
|
|
34
|
+
* The only issue kinds that ever raise a friend-facing macOS banner — the
|
|
35
|
+
* user-ACTIONABLE failures, where the friend can sign in or add a key and the
|
|
36
|
+
* problem clears. Everything else (a transient codex/claude probe failure, an
|
|
37
|
+
* index-write or save error, a backend timeout) is operator-only: surfaced in
|
|
38
|
+
* `rift doctor` / `rift status` and the logs, never a banner, because a
|
|
39
|
+
* non-technical friend cannot act on it and Rift retries it on its own.
|
|
40
|
+
*
|
|
41
|
+
* New kinds default to operator-only (fail-closed): add a kind here only when
|
|
42
|
+
* there is a safe, concrete action the friend can take.
|
|
43
|
+
*/
|
|
44
|
+
export const FRIEND_NOTIFY_KINDS = new Set([
|
|
45
|
+
"codex_auth_expired",
|
|
46
|
+
"claude_auth_expired",
|
|
47
|
+
"voyage_key_missing",
|
|
48
|
+
// NOT voyage_embed_errors: "key present but embedding failed" is not cleanly
|
|
49
|
+
// friend-actionable — it spans an invalid key AND a network/provider flake.
|
|
50
|
+
// It stays operator-only until the cause is split into its own kind
|
|
51
|
+
// (voyage_key_invalid → friend banner, voyage_embed_errors → operator).
|
|
52
|
+
]);
|
|
28
53
|
/** Cause identity for an issue: explicit fingerprint, else its kind. */
|
|
29
54
|
function issueFingerprint(issue) {
|
|
30
55
|
return issue.fingerprint ?? issue.kind;
|
|
@@ -45,16 +70,34 @@ export function buildNotificationPayload(issue) {
|
|
|
45
70
|
* Decide which notifications to send this tick and what state to persist.
|
|
46
71
|
* Pure: no IO, no clock except the injected `now`.
|
|
47
72
|
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
73
|
+
* Eligible issues are the intersection of `daemonObservable` (the daemon can
|
|
74
|
+
* see them) and `FRIEND_NOTIFY_KINDS` (the friend can act on them) — so a
|
|
75
|
+
* transient probe/index/save failure never reaches a banner.
|
|
76
|
+
*
|
|
77
|
+
* The dedup memory survives a healthy run: a record is retained until its 24h
|
|
78
|
+
* cooldown elapses, even on ticks where the issue is absent. That is the flood
|
|
79
|
+
* fix — without it, one healthy poll wiped the "already warned you" memory and
|
|
80
|
+
* the next recurrence re-notified, defeating the daily limit.
|
|
51
81
|
*/
|
|
52
82
|
export function planNotifications(input) {
|
|
53
83
|
const { issues, state, now } = input;
|
|
54
|
-
const eligible = issues.filter((i) => i.daemonObservable);
|
|
55
|
-
const
|
|
56
|
-
const nextActive = {};
|
|
84
|
+
const eligible = issues.filter((i) => i.daemonObservable && FRIEND_NOTIFY_KINDS.has(i.kind));
|
|
85
|
+
const presentKinds = new Set(eligible.map((i) => i.kind));
|
|
57
86
|
const notifications = [];
|
|
87
|
+
const nextActive = {};
|
|
88
|
+
// Carry over prior records for kinds NOT failing this tick, as long as their
|
|
89
|
+
// cooldown window has not elapsed. This keeps the "already warned" memory
|
|
90
|
+
// alive across a healthy run, so an intermittent failure notifies once per
|
|
91
|
+
// day rather than on every recurrence. Expired records are dropped, so a
|
|
92
|
+
// genuine later recurrence notifies fresh.
|
|
93
|
+
for (const [kind, record] of Object.entries(state.active)) {
|
|
94
|
+
if (presentKinds.has(kind))
|
|
95
|
+
continue;
|
|
96
|
+
const lastMs = Date.parse(record.last_notified_at);
|
|
97
|
+
const fresh = !Number.isNaN(lastMs) && now - lastMs < RENOTIFY_INTERVAL_MS;
|
|
98
|
+
if (fresh)
|
|
99
|
+
nextActive[kind] = record;
|
|
100
|
+
}
|
|
58
101
|
for (const issue of eligible) {
|
|
59
102
|
const prior = state.active[issue.kind];
|
|
60
103
|
const fingerprint = issueFingerprint(issue);
|
|
@@ -66,7 +109,7 @@ export function planNotifications(input) {
|
|
|
66
109
|
};
|
|
67
110
|
};
|
|
68
111
|
if (!prior) {
|
|
69
|
-
//
|
|
112
|
+
// First transition into failure → notify.
|
|
70
113
|
notify();
|
|
71
114
|
continue;
|
|
72
115
|
}
|
|
@@ -84,13 +127,10 @@ export function planNotifications(input) {
|
|
|
84
127
|
notify();
|
|
85
128
|
}
|
|
86
129
|
else {
|
|
87
|
-
// Already notified within the window → stay quiet, keep record.
|
|
130
|
+
// Already notified within the window → stay quiet, keep the record.
|
|
88
131
|
nextActive[issue.kind] = prior;
|
|
89
132
|
}
|
|
90
133
|
}
|
|
91
|
-
// Anything previously active but no longer present has resolved; it is
|
|
92
|
-
// simply absent from `nextActive`, so a later recurrence notifies fresh.
|
|
93
|
-
void eligibleKinds;
|
|
94
134
|
return { notifications, nextState: { active: nextActive } };
|
|
95
135
|
}
|
|
96
136
|
/** Absolute path to the dedup-state file under the data dir. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notify.js","sourceRoot":"","sources":["../../../src/diagnostics/notify.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"notify.js","sourceRoot":"","sources":["../../../src/diagnostics/notify.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The single source of truth for chunk MARKERS — how a row declares it is one
|
|
3
|
+
* piece of a larger logical document/conversation, and how readers recover the
|
|
4
|
+
* parent grouping. Every producer (indexer, save, ingest, rebuild) and every
|
|
5
|
+
* consumer (retrieval grouping, reconcile, dedup) imports from here, so there is
|
|
6
|
+
* exactly one marker contract.
|
|
7
|
+
*
|
|
8
|
+
* Representation:
|
|
9
|
+
* - Conversations carry explicit columns `parent_id`, `chunk_index`,
|
|
10
|
+
* `chunk_count` (all strings; empty = legacy/unchunked).
|
|
11
|
+
* - Documents carry `chunk_index` / `chunk_count` inside the existing
|
|
12
|
+
* `metadata` JSON; the parent key is the already-indexed `source_path`.
|
|
13
|
+
*
|
|
14
|
+
* The explicit `chunk_count` IS the marker: `chunk_count > 1` means "this row is
|
|
15
|
+
* part of a chunk set". A row WITHOUT that marker is never grouped — sharing a
|
|
16
|
+
* `source_path` or `idempotency_key` alone must not cause a collapse. Ordinals
|
|
17
|
+
* are stored explicitly (not parsed out of the row id), so completeness checks
|
|
18
|
+
* and honest "section k of N" display never treat the id as the source of truth.
|
|
19
|
+
*/
|
|
20
|
+
import type { TableName } from "../storage/tables.js";
|
|
21
|
+
export interface ChunkMarker {
|
|
22
|
+
/** Parent key value: `source_path` for docs, `parent_id` for conversations. */
|
|
23
|
+
parentId: string;
|
|
24
|
+
/** 0-based ordinal within the set. */
|
|
25
|
+
index: number;
|
|
26
|
+
/** Total chunks in the set (> 1 when this is genuinely chunked). */
|
|
27
|
+
count: number;
|
|
28
|
+
}
|
|
29
|
+
/** Separators for chunk row ids. Distinct per family for readability; ids are
|
|
30
|
+
* unique either way and are NOT load-bearing for ordering (use chunk_index). */
|
|
31
|
+
export declare const DOC_CHUNK_SEP = ":";
|
|
32
|
+
export declare const CONV_CHUNK_SEP = "::";
|
|
33
|
+
/** Read the chunk marker from a conversation row, or null if unchunked/legacy. */
|
|
34
|
+
export declare function readConversationChunkMarker(row: Record<string, unknown>): ChunkMarker | null;
|
|
35
|
+
/** Read the chunk marker from a structured-doc row, or null if unchunked/legacy. */
|
|
36
|
+
export declare function readDocChunkMarker(row: Record<string, unknown>): ChunkMarker | null;
|
|
37
|
+
/**
|
|
38
|
+
* Namespaced parent key for retrieval grouping, or `null` when the row carries
|
|
39
|
+
* NO explicit chunk marker (the flag-off / legacy case — never grouped).
|
|
40
|
+
*
|
|
41
|
+
* Namespacing guarantees mixed-vintage / cross-table rows can never collapse:
|
|
42
|
+
* - docs → `doc|<source_table>|<source_path>` (so `structured_docs` vs
|
|
43
|
+
* `structured_docs_local` with the same path stay separate)
|
|
44
|
+
* - convs → `conv|<source>|<parent_id>`
|
|
45
|
+
*/
|
|
46
|
+
export declare function parentKeyForRow(sourceTable: TableName, row: Record<string, unknown>): string | null;
|
|
47
|
+
/** True iff the row is part of a genuine chunk set (`chunk_count > 1`). */
|
|
48
|
+
export declare function isChunked(sourceTable: TableName, row: Record<string, unknown>): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Unified chunk-marker reader across the conversation and document families,
|
|
51
|
+
* or `null` for an unchunked/legacy row (no marker / `chunk_count <= 1`) and for
|
|
52
|
+
* digests (which never chunk). Lets the read-side (expand stitching) inspect a
|
|
53
|
+
* row's position in its set without re-deriving the per-family column vs metadata
|
|
54
|
+
* split. `parentId` is the raw column value (`parent_id` / `source_path`), not the
|
|
55
|
+
* namespaced retrieval key.
|
|
56
|
+
*/
|
|
57
|
+
export declare function readChunkMarker(sourceTable: TableName, row: Record<string, unknown>): ChunkMarker | null;
|
|
58
|
+
/** Conversation chunk columns. count <= 1 → empty markers (matches seed/legacy). */
|
|
59
|
+
export declare function conversationChunkColumns(parentId: string, index: number, count: number): {
|
|
60
|
+
parent_id: string;
|
|
61
|
+
chunk_index: string;
|
|
62
|
+
chunk_count: string;
|
|
63
|
+
};
|
|
64
|
+
/** Merge chunk ordinals into a doc metadata object. count <= 1 → unchanged
|
|
65
|
+
* (NO `chunk_*` keys), so a single/legacy doc stays byte-identical. */
|
|
66
|
+
export declare function docChunkMetadata(base: Record<string, unknown>, index: number, count: number): Record<string, unknown>;
|
|
67
|
+
export declare function convChunkId(parentId: string, index: number): string;
|
|
68
|
+
export declare function docChunkId(fileId: string, index: number): string;
|
|
69
|
+
/** The largest declared `chunk_count` across a set of rows (≥ 1). */
|
|
70
|
+
export declare function expectedChunkCount(rows: Record<string, unknown>[]): number;
|
|
71
|
+
/**
|
|
72
|
+
* True iff the rows already indexed for a parent form a COMPLETE set. Used by
|
|
73
|
+
* save/ingest/reconcile dedup so a partially-written set (crash mid-append) is
|
|
74
|
+
* repaired rather than mistaken for "already indexed".
|
|
75
|
+
*
|
|
76
|
+
* Completeness is stricter than a row count: a chunked set is complete only when
|
|
77
|
+
* every chunk index `0 .. count-1` is present EXACTLY once and every row agrees
|
|
78
|
+
* on the same `chunk_count`. This rejects the degenerate set that a bare
|
|
79
|
+
* `rows.length >= count` check would wave through — e.g. a duplicated chunk 0
|
|
80
|
+
* with a missing chunk 1 (length 2, count 2, but broken). An unchunked set
|
|
81
|
+
* (`count <= 1`, all legacy/`/ingest`-job rows) keeps the legacy semantics: any
|
|
82
|
+
* existing row counts as complete, so this never changes flag-off behavior.
|
|
83
|
+
*/
|
|
84
|
+
export declare function chunkSetComplete(rows: Record<string, unknown>[]): boolean;
|
|
85
|
+
//# sourceMappingURL=chunk-meta.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunk-meta.d.ts","sourceRoot":"","sources":["../../../src/ingestion/chunk-meta.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEtD,MAAM,WAAW,WAAW;IAC1B,+EAA+E;IAC/E,QAAQ,EAAE,MAAM,CAAC;IACjB,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC;CACf;AAED;iFACiF;AACjF,eAAO,MAAM,aAAa,MAAM,CAAC;AACjC,eAAO,MAAM,cAAc,OAAO,CAAC;AAgCnC,kFAAkF;AAClF,wBAAgB,2BAA2B,CACzC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC3B,WAAW,GAAG,IAAI,CAMpB;AAED,oFAAoF;AACpF,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC3B,WAAW,GAAG,IAAI,CAQpB;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,WAAW,EAAE,SAAS,EACtB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC3B,MAAM,GAAG,IAAI,CAaf;AAED,2EAA2E;AAC3E,wBAAgB,SAAS,CACvB,WAAW,EAAE,SAAS,EACtB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC3B,OAAO,CAET;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,WAAW,EAAE,SAAS,EACtB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC3B,WAAW,GAAG,IAAI,CAQpB;AAID,oFAAoF;AACpF,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACZ;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAOjE;AAED;wEACwE;AACxE,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACZ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAGzB;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAEnE;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhE;AAID,qEAAqE;AACrE,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,MAAM,CAI1E;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,OAAO,CAczE"}
|