crewly 1.20.356 → 1.20.358
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/config/constants.ts +11 -0
- package/dist/backend/backend/src/constants.d.ts +254 -17
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +257 -17
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +70 -4
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts +10 -2
- package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.js +27 -2
- package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/fresh-task-conversation.service.d.ts +34 -1
- package/dist/backend/backend/src/services/agent/fresh-task-conversation.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/fresh-task-conversation.service.js +69 -13
- package/dist/backend/backend/src/services/agent/fresh-task-conversation.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/idle-detection.service.d.ts +8 -0
- package/dist/backend/backend/src/services/agent/idle-detection.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/idle-detection.service.js +26 -2
- package/dist/backend/backend/src/services/agent/idle-detection.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/resource-mode.service.d.ts +9 -0
- package/dist/backend/backend/src/services/agent/resource-mode.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/resource-mode.service.js +16 -0
- package/dist/backend/backend/src/services/agent/resource-mode.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/runtime-session-recovery.d.ts +44 -3
- package/dist/backend/backend/src/services/agent/runtime-session-recovery.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/runtime-session-recovery.js +126 -11
- package/dist/backend/backend/src/services/agent/runtime-session-recovery.js.map +1 -1
- package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts +2 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.js +9 -1
- package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.js.map +1 -1
- package/dist/backend/backend/src/services/memory/agent-memory-refresh.service.d.ts +150 -0
- package/dist/backend/backend/src/services/memory/agent-memory-refresh.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/memory/agent-memory-refresh.service.js +319 -0
- package/dist/backend/backend/src/services/memory/agent-memory-refresh.service.js.map +1 -0
- package/dist/backend/backend/src/services/memory/auto-learning.subscriber.d.ts +9 -7
- package/dist/backend/backend/src/services/memory/auto-learning.subscriber.d.ts.map +1 -1
- package/dist/backend/backend/src/services/memory/auto-learning.subscriber.js +19 -17
- package/dist/backend/backend/src/services/memory/auto-learning.subscriber.js.map +1 -1
- package/dist/backend/backend/src/services/memory/memory.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/memory/memory.service.js +11 -0
- package/dist/backend/backend/src/services/memory/memory.service.js.map +1 -1
- package/dist/backend/backend/src/services/memory/startup-briefing.service.d.ts +104 -0
- package/dist/backend/backend/src/services/memory/startup-briefing.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/memory/startup-briefing.service.js +302 -0
- package/dist/backend/backend/src/services/memory/startup-briefing.service.js.map +1 -0
- package/dist/backend/backend/src/services/messaging/owner-thread-sentinel.service.d.ts +33 -1
- package/dist/backend/backend/src/services/messaging/owner-thread-sentinel.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/owner-thread-sentinel.service.js +69 -4
- package/dist/backend/backend/src/services/messaging/owner-thread-sentinel.service.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/owner-thread-sentinel.wiring.d.ts +24 -1
- package/dist/backend/backend/src/services/messaging/owner-thread-sentinel.wiring.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/owner-thread-sentinel.wiring.js +54 -3
- package/dist/backend/backend/src/services/messaging/owner-thread-sentinel.wiring.js.map +1 -1
- package/dist/backend/backend/src/services/orc/owner-completion-report.service.d.ts +9 -0
- package/dist/backend/backend/src/services/orc/owner-completion-report.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/orc/owner-completion-report.service.js +16 -2
- package/dist/backend/backend/src/services/orc/owner-completion-report.service.js.map +1 -1
- package/dist/backend/backend/src/services/project-tickets/ticket-prefixes.d.ts +30 -0
- package/dist/backend/backend/src/services/project-tickets/ticket-prefixes.d.ts.map +1 -0
- package/dist/backend/backend/src/services/project-tickets/ticket-prefixes.js +48 -0
- package/dist/backend/backend/src/services/project-tickets/ticket-prefixes.js.map +1 -0
- package/dist/backend/backend/src/services/reconciler/reconciler.service.d.ts +8 -0
- package/dist/backend/backend/src/services/reconciler/reconciler.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/reconciler/reconciler.service.js +29 -8
- package/dist/backend/backend/src/services/reconciler/reconciler.service.js.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.service.d.ts +27 -0
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.service.js +78 -24
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.service.js.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.wiring.d.ts +23 -0
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.wiring.d.ts.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.wiring.js +38 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.wiring.js.map +1 -1
- package/dist/backend/backend/src/services/slack/agent-coordination.d.ts +119 -0
- package/dist/backend/backend/src/services/slack/agent-coordination.d.ts.map +1 -0
- package/dist/backend/backend/src/services/slack/agent-coordination.js +174 -0
- package/dist/backend/backend/src/services/slack/agent-coordination.js.map +1 -0
- package/dist/backend/backend/src/services/slack/slack-initializer.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-initializer.js +7 -0
- package/dist/backend/backend/src/services/slack/slack-initializer.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.d.ts +167 -0
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.js +619 -9
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-thread-context.service.d.ts +22 -0
- package/dist/backend/backend/src/services/slack/slack-thread-context.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-thread-context.service.js +49 -12
- package/dist/backend/backend/src/services/slack/slack-thread-context.service.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-typing-placeholder.service.d.ts +7 -0
- package/dist/backend/backend/src/services/slack/slack-typing-placeholder.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-typing-placeholder.service.js +25 -4
- package/dist/backend/backend/src/services/slack/slack-typing-placeholder.service.js.map +1 -1
- package/dist/backend/backend/src/services/team-move/team-move-chat.d.ts +21 -1
- package/dist/backend/backend/src/services/team-move/team-move-chat.d.ts.map +1 -1
- package/dist/backend/backend/src/services/team-move/team-move-chat.js +54 -2
- package/dist/backend/backend/src/services/team-move/team-move-chat.js.map +1 -1
- package/dist/backend/backend/src/services/team-move/team-move-exporter.d.ts +9 -4
- package/dist/backend/backend/src/services/team-move/team-move-exporter.d.ts.map +1 -1
- package/dist/backend/backend/src/services/team-move/team-move-exporter.js +32 -10
- package/dist/backend/backend/src/services/team-move/team-move-exporter.js.map +1 -1
- package/dist/backend/backend/src/services/team-move/team-move-importer.d.ts +19 -0
- package/dist/backend/backend/src/services/team-move/team-move-importer.d.ts.map +1 -1
- package/dist/backend/backend/src/services/team-move/team-move-importer.js +78 -3
- package/dist/backend/backend/src/services/team-move/team-move-importer.js.map +1 -1
- package/dist/backend/backend/src/services/team-move/team-move-runtime.d.ts.map +1 -1
- package/dist/backend/backend/src/services/team-move/team-move-runtime.js +8 -0
- package/dist/backend/backend/src/services/team-move/team-move-runtime.js.map +1 -1
- package/dist/backend/backend/src/services/team-move/team-move-transcripts.d.ts +106 -0
- package/dist/backend/backend/src/services/team-move/team-move-transcripts.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team-move/team-move-transcripts.js +212 -0
- package/dist/backend/backend/src/services/team-move/team-move-transcripts.js.map +1 -0
- package/dist/backend/backend/src/services/team-move/team-move.types.d.ts +20 -0
- package/dist/backend/backend/src/services/team-move/team-move.types.d.ts.map +1 -1
- package/dist/backend/backend/src/services/team-move/team-move.types.js.map +1 -1
- package/dist/backend/backend/src/services/v3/agent-auto-claim.service.d.ts +2 -2
- package/dist/backend/backend/src/services/v3/agent-auto-claim.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/v3/agent-auto-claim.service.js +11 -4
- package/dist/backend/backend/src/services/v3/agent-auto-claim.service.js.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-backlinks.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-backlinks.service.js +3 -0
- package/dist/backend/backend/src/services/wiki/wiki-backlinks.service.js.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-bookkeep.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-bookkeep.service.js +4 -1
- package/dist/backend/backend/src/services/wiki/wiki-bookkeep.service.js.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-cleanup.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-cleanup.service.js +4 -0
- package/dist/backend/backend/src/services/wiki/wiki-cleanup.service.js.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-ingest.service.d.ts +33 -4
- package/dist/backend/backend/src/services/wiki/wiki-ingest.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-ingest.service.js +75 -7
- package/dist/backend/backend/src/services/wiki/wiki-ingest.service.js.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-lint.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-lint.service.js +3 -1
- package/dist/backend/backend/src/services/wiki/wiki-lint.service.js.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-log-compile.service.d.ts +116 -0
- package/dist/backend/backend/src/services/wiki/wiki-log-compile.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-log-compile.service.js +227 -0
- package/dist/backend/backend/src/services/wiki/wiki-log-compile.service.js.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-log-entries.d.ts +142 -0
- package/dist/backend/backend/src/services/wiki/wiki-log-entries.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-log-entries.js +222 -0
- package/dist/backend/backend/src/services/wiki/wiki-log-entries.js.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-log-rotation.service.d.ts +93 -0
- package/dist/backend/backend/src/services/wiki/wiki-log-rotation.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-log-rotation.service.js +142 -0
- package/dist/backend/backend/src/services/wiki/wiki-log-rotation.service.js.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-maintenance.service.d.ts +104 -0
- package/dist/backend/backend/src/services/wiki/wiki-maintenance.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-maintenance.service.js +192 -0
- package/dist/backend/backend/src/services/wiki/wiki-maintenance.service.js.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-query.service.d.ts +3 -2
- package/dist/backend/backend/src/services/wiki/wiki-query.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-query.service.js +23 -39
- package/dist/backend/backend/src/services/wiki/wiki-query.service.js.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-queue-drain.service.d.ts +105 -0
- package/dist/backend/backend/src/services/wiki/wiki-queue-drain.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-queue-drain.service.js +195 -0
- package/dist/backend/backend/src/services/wiki/wiki-queue-drain.service.js.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-recent.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-recent.service.js +3 -0
- package/dist/backend/backend/src/services/wiki/wiki-recent.service.js.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-search.service.d.ts +28 -5
- package/dist/backend/backend/src/services/wiki/wiki-search.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-search.service.js +96 -25
- package/dist/backend/backend/src/services/wiki/wiki-search.service.js.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-vault-walk.d.ts +11 -0
- package/dist/backend/backend/src/services/wiki/wiki-vault-walk.d.ts.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-vault-walk.js +17 -1
- package/dist/backend/backend/src/services/wiki/wiki-vault-walk.js.map +1 -1
- package/dist/backend/build-info.json +2 -2
- package/dist/backend/config/constants.d.ts +11 -0
- package/dist/backend/config/constants.d.ts.map +1 -1
- package/dist/backend/config/constants.js +11 -0
- package/dist/backend/config/constants.js.map +1 -1
- package/dist/cli/backend/src/constants.d.ts +254 -17
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +257 -17
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts +10 -2
- package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/agent-registration.service.js +27 -2
- package/dist/cli/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/cli/backend/src/services/agent/fresh-task-conversation.service.d.ts +34 -1
- package/dist/cli/backend/src/services/agent/fresh-task-conversation.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/fresh-task-conversation.service.js +69 -13
- package/dist/cli/backend/src/services/agent/fresh-task-conversation.service.js.map +1 -1
- package/dist/cli/backend/src/services/agent/resource-mode.service.d.ts +9 -0
- package/dist/cli/backend/src/services/agent/resource-mode.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/resource-mode.service.js +16 -0
- package/dist/cli/backend/src/services/agent/resource-mode.service.js.map +1 -1
- package/dist/cli/backend/src/services/agent/runtime-session-recovery.d.ts +44 -3
- package/dist/cli/backend/src/services/agent/runtime-session-recovery.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/runtime-session-recovery.js +126 -11
- package/dist/cli/backend/src/services/agent/runtime-session-recovery.js.map +1 -1
- package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts +2 -0
- package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.js +9 -1
- package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.js.map +1 -1
- package/dist/cli/backend/src/services/memory/memory.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/memory/memory.service.js +11 -0
- package/dist/cli/backend/src/services/memory/memory.service.js.map +1 -1
- package/dist/cli/backend/src/services/memory/startup-briefing.service.d.ts +104 -0
- package/dist/cli/backend/src/services/memory/startup-briefing.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/memory/startup-briefing.service.js +302 -0
- package/dist/cli/backend/src/services/memory/startup-briefing.service.js.map +1 -0
- package/dist/cli/backend/src/services/messaging/owner-thread-sentinel.service.d.ts +33 -1
- package/dist/cli/backend/src/services/messaging/owner-thread-sentinel.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/messaging/owner-thread-sentinel.service.js +69 -4
- package/dist/cli/backend/src/services/messaging/owner-thread-sentinel.service.js.map +1 -1
- package/dist/cli/backend/src/services/slack/agent-coordination.d.ts +119 -0
- package/dist/cli/backend/src/services/slack/agent-coordination.d.ts.map +1 -0
- package/dist/cli/backend/src/services/slack/agent-coordination.js +174 -0
- package/dist/cli/backend/src/services/slack/agent-coordination.js.map +1 -0
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts +167 -0
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.js +619 -9
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-thread-context.service.d.ts +22 -0
- package/dist/cli/backend/src/services/slack/slack-thread-context.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-thread-context.service.js +49 -12
- package/dist/cli/backend/src/services/slack/slack-thread-context.service.js.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-typing-placeholder.service.d.ts +7 -0
- package/dist/cli/backend/src/services/slack/slack-typing-placeholder.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-typing-placeholder.service.js +25 -4
- package/dist/cli/backend/src/services/slack/slack-typing-placeholder.service.js.map +1 -1
- package/dist/cli/backend/src/services/wiki/wiki-ingest.service.d.ts +33 -4
- package/dist/cli/backend/src/services/wiki/wiki-ingest.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/wiki/wiki-ingest.service.js +75 -7
- package/dist/cli/backend/src/services/wiki/wiki-ingest.service.js.map +1 -1
- package/dist/cli/backend/src/services/wiki/wiki-log-entries.d.ts +142 -0
- package/dist/cli/backend/src/services/wiki/wiki-log-entries.d.ts.map +1 -0
- package/dist/cli/backend/src/services/wiki/wiki-log-entries.js +222 -0
- package/dist/cli/backend/src/services/wiki/wiki-log-entries.js.map +1 -0
- package/dist/cli/backend/src/services/wiki/wiki-recent.service.d.ts +51 -0
- package/dist/cli/backend/src/services/wiki/wiki-recent.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/wiki/wiki-recent.service.js +105 -0
- package/dist/cli/backend/src/services/wiki/wiki-recent.service.js.map +1 -0
- package/dist/cli/backend/src/services/wiki/wiki-search.service.d.ts +28 -5
- package/dist/cli/backend/src/services/wiki/wiki-search.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/wiki/wiki-search.service.js +96 -25
- package/dist/cli/backend/src/services/wiki/wiki-search.service.js.map +1 -1
- package/dist/cli/backend/src/services/wiki/wiki-vault-walk.d.ts +11 -0
- package/dist/cli/backend/src/services/wiki/wiki-vault-walk.d.ts.map +1 -1
- package/dist/cli/backend/src/services/wiki/wiki-vault-walk.js +17 -1
- package/dist/cli/backend/src/services/wiki/wiki-vault-walk.js.map +1 -1
- package/dist/cli/config/constants.d.ts +11 -0
- package/dist/cli/config/constants.d.ts.map +1 -1
- package/dist/cli/config/constants.js +11 -0
- package/dist/cli/config/constants.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The vault activity log (`llm-curated/log.md`) as entries.
|
|
3
|
+
*
|
|
4
|
+
* One place that knows the entry format `WikiIngestService` appends:
|
|
5
|
+
*
|
|
6
|
+
* ## [<ISO>] <sourceType> | <caller>
|
|
7
|
+
*
|
|
8
|
+
* ref: <sourceRef>
|
|
9
|
+
*
|
|
10
|
+
* <body>
|
|
11
|
+
*
|
|
12
|
+
* Used by search (one document per recent entry), rotation (carry forward
|
|
13
|
+
* the recent non-noise entries), the digest compiler and the startup
|
|
14
|
+
* briefing. Also decides what counts as a content-free entry (#1345): a
|
|
15
|
+
* templated state transition carries nothing a reader could use.
|
|
16
|
+
*
|
|
17
|
+
* @module services/wiki/wiki-log-entries
|
|
18
|
+
*/
|
|
19
|
+
import { createHash } from 'crypto';
|
|
20
|
+
import { WIKI_LOG_CONSTANTS } from '../../constants.js';
|
|
21
|
+
/** Header a fresh `log.md` starts with. */
|
|
22
|
+
export const WIKI_LOG_HEADER = '# Activity log\n\nAppend-only log of ingested sources. Each entry: `## [<ISO>] <sourceType> | <caller>`.\n';
|
|
23
|
+
const HEADER_RE = /^## \[([^\]]+)\]\s+(\S+)\s+\|\s+(.+)$/gm;
|
|
24
|
+
/**
|
|
25
|
+
* Templated records that carry no information for a reader:
|
|
26
|
+
* - auto-learning state transitions (`[pattern] [[WorkItem-x]] task:done running→done. timestamp=… Source: …`);
|
|
27
|
+
* - the same shape without the category tag;
|
|
28
|
+
* - task-completion stubs (`Task completed: …`) that belong on the WorkItem.
|
|
29
|
+
*/
|
|
30
|
+
const NOISE_PATTERNS = [
|
|
31
|
+
/\[\[(?:WorkItem|Mission)-[^\]]+\]\]\s+(?:task|mission):[a-z_]+\s+\S*\.?\s*(?:team=\S+\s*)?(?:mission=\S+\s*)?(?:resolver=\S+\s*)?timestamp=/i,
|
|
32
|
+
/^\s*(?:\([a-z_]+\)\s*)?(?:\[[a-z_]+\]\s*)?Task (?:completed|done)(?: by [^:]+)?:\s*\S/i,
|
|
33
|
+
];
|
|
34
|
+
/**
|
|
35
|
+
* Whether a learning / log body is a content-free templated record.
|
|
36
|
+
*
|
|
37
|
+
* @param body - Entry body or learning text
|
|
38
|
+
* @returns True when the text matches a known templated shape or is blank
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* isNoiseLogBody('(learning) [pattern] [[WorkItem-1]] task:done running→done. timestamp=2026-10-17T00:00:00Z. Source: x.'); // true
|
|
43
|
+
* isNoiseLogBody('(gotcha) complete-task rejects queued→done; accept-task first.'); // false
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export function isNoiseLogBody(body) {
|
|
47
|
+
if (!body)
|
|
48
|
+
return true;
|
|
49
|
+
const text = body.trim();
|
|
50
|
+
if (text.length === 0)
|
|
51
|
+
return true;
|
|
52
|
+
return NOISE_PATTERNS.some((re) => re.test(text));
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Conversation handover snapshots (`**Conversation handover — <agent> — task <id>** (fact) …`)
|
|
56
|
+
* that the fresh-conversation path mirrors into the vault. They are state,
|
|
57
|
+
* not knowledge: a thousand of them a week on one machine. They stay in the
|
|
58
|
+
* log (the agent is pointed at them) but are not knowledge for search, the
|
|
59
|
+
* digest, memory or the briefing.
|
|
60
|
+
*
|
|
61
|
+
* @param body - Entry body
|
|
62
|
+
* @returns True for a handover snapshot
|
|
63
|
+
*/
|
|
64
|
+
export function isHandoverLogBody(body) {
|
|
65
|
+
if (!body)
|
|
66
|
+
return false;
|
|
67
|
+
return /^\s*(?:\([a-z_-]+\)\s*)?\*\*Conversation handover\b/i.test(body.trim());
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Normalised form of a body used for duplicate detection: whitespace
|
|
71
|
+
* collapsed, case folded, trailing punctuation dropped.
|
|
72
|
+
*
|
|
73
|
+
* @param body - Entry body
|
|
74
|
+
* @returns Normalised text
|
|
75
|
+
*/
|
|
76
|
+
export function normalizeLogBody(body) {
|
|
77
|
+
return body.replace(/\s+/g, ' ').trim().toLowerCase().replace(/[.。]+$/, '');
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Stable key of an entry's content (sha1 of the normalised body). Two
|
|
81
|
+
* entries with the same body share a key whatever their timestamps.
|
|
82
|
+
*
|
|
83
|
+
* @param body - Entry body
|
|
84
|
+
* @returns 40-char hex digest
|
|
85
|
+
*/
|
|
86
|
+
export function logBodyKey(body) {
|
|
87
|
+
return createHash('sha1').update(normalizeLogBody(body)).digest('hex');
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Parse a whole `log.md` into entries, in file order. Text before the
|
|
91
|
+
* first entry header (the preamble, a migrated learnings import) is not an
|
|
92
|
+
* entry and is dropped.
|
|
93
|
+
*
|
|
94
|
+
* @param raw - File content
|
|
95
|
+
* @returns Entries in file order
|
|
96
|
+
*/
|
|
97
|
+
export function parseLogEntries(raw) {
|
|
98
|
+
const matches = [];
|
|
99
|
+
HEADER_RE.lastIndex = 0;
|
|
100
|
+
let m;
|
|
101
|
+
while ((m = HEADER_RE.exec(raw))) {
|
|
102
|
+
matches.push({ idx: m.index, ts: m[1], sourceType: m[2], caller: m[3].trim() });
|
|
103
|
+
}
|
|
104
|
+
const entries = [];
|
|
105
|
+
for (let i = 0; i < matches.length; i++) {
|
|
106
|
+
const start = matches[i].idx;
|
|
107
|
+
const end = i + 1 < matches.length ? matches[i + 1].idx : raw.length;
|
|
108
|
+
const block = raw.slice(start, end);
|
|
109
|
+
const refMatch = block.match(/^ref:\s*(.+)$/m);
|
|
110
|
+
let body = '';
|
|
111
|
+
if (refMatch) {
|
|
112
|
+
const refLineEnd = block.indexOf(refMatch[0]) + refMatch[0].length;
|
|
113
|
+
body = block.slice(refLineEnd).replace(/^\n+/, '').trim();
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
// Entries written by hand or migrated: body is everything after the header line.
|
|
117
|
+
body = block.slice(block.indexOf('\n') + 1).trim();
|
|
118
|
+
}
|
|
119
|
+
entries.push({
|
|
120
|
+
timestamp: matches[i].ts,
|
|
121
|
+
timestampMs: Date.parse(matches[i].ts),
|
|
122
|
+
sourceType: matches[i].sourceType,
|
|
123
|
+
caller: matches[i].caller,
|
|
124
|
+
ref: refMatch ? refMatch[1].trim() : '',
|
|
125
|
+
body,
|
|
126
|
+
raw: block.replace(/\s+$/, ''),
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
return entries;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Serialise an entry back into the append format (leading blank line,
|
|
133
|
+
* header, ref line, body, trailing blank line).
|
|
134
|
+
*
|
|
135
|
+
* @param entry - Entry to serialise
|
|
136
|
+
* @returns Markdown block
|
|
137
|
+
*/
|
|
138
|
+
export function serializeLogEntry(entry) {
|
|
139
|
+
return ['', `## [${entry.timestamp}] ${entry.sourceType} | ${entry.caller}`, '', `ref: ${entry.ref}`, '', entry.body, ''].join('\n');
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* The entries from the last `days` days that carry content, newest first,
|
|
143
|
+
* with duplicate bodies collapsed (the newest copy wins). Handover
|
|
144
|
+
* snapshots are left out unless `includeHandovers` is set (rotation keeps
|
|
145
|
+
* them; search, digest, memory and briefing do not).
|
|
146
|
+
*
|
|
147
|
+
* @param entries - Parsed entries (any order)
|
|
148
|
+
* @param days - Window length
|
|
149
|
+
* @param now - Current epoch ms
|
|
150
|
+
* @param limit - Cap on returned entries
|
|
151
|
+
* @param options - `includeHandovers` keeps handover snapshots
|
|
152
|
+
* @returns Recent, non-noise, deduped entries, newest first
|
|
153
|
+
*/
|
|
154
|
+
export function recentContentEntries(entries, days, now = Date.now(), limit = Number.MAX_SAFE_INTEGER, options = {}) {
|
|
155
|
+
const cutoff = now - days * 24 * 60 * 60 * 1000;
|
|
156
|
+
const seen = new Set();
|
|
157
|
+
const out = [];
|
|
158
|
+
const sorted = [...entries].sort((a, b) => (b.timestampMs || 0) - (a.timestampMs || 0));
|
|
159
|
+
for (const e of sorted) {
|
|
160
|
+
if (!Number.isFinite(e.timestampMs) || e.timestampMs < cutoff)
|
|
161
|
+
continue;
|
|
162
|
+
if (isNoiseLogBody(e.body))
|
|
163
|
+
continue;
|
|
164
|
+
if (!options.includeHandovers && isHandoverLogBody(e.body))
|
|
165
|
+
continue;
|
|
166
|
+
const key = logBodyKey(e.body);
|
|
167
|
+
if (seen.has(key))
|
|
168
|
+
continue;
|
|
169
|
+
seen.add(key);
|
|
170
|
+
out.push(e);
|
|
171
|
+
if (out.length >= limit)
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
return out;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Vault-relative "path" of a log entry as surfaced by search:
|
|
178
|
+
* `llm-curated/log.md#<ISO timestamp>`.
|
|
179
|
+
*
|
|
180
|
+
* @param entry - Entry
|
|
181
|
+
* @returns Pseudo path
|
|
182
|
+
*/
|
|
183
|
+
export function logEntryPath(entry) {
|
|
184
|
+
return `${WIKI_LOG_CONSTANTS.LOG_RELATIVE_PATH}${WIKI_LOG_CONSTANTS.ENTRY_PATH_SEPARATOR}${entry.timestamp}`;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Whether a vault-relative path points at a log entry (as opposed to a page).
|
|
188
|
+
*
|
|
189
|
+
* @param relativePath - Path from a search hit
|
|
190
|
+
* @returns True for `llm-curated/log.md#…`
|
|
191
|
+
*/
|
|
192
|
+
export function isLogEntryPath(relativePath) {
|
|
193
|
+
return relativePath.startsWith(`${WIKI_LOG_CONSTANTS.LOG_RELATIVE_PATH}${WIKI_LOG_CONSTANTS.ENTRY_PATH_SEPARATOR}`);
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* The `(category)` prefix `MemoryService` puts on a mirrored memory
|
|
197
|
+
* (`(gotcha) …`, `(decision) …`) or the `[tag]` an auto-recorder uses.
|
|
198
|
+
*
|
|
199
|
+
* @param body - Entry body
|
|
200
|
+
* @returns Lower-case category, or 'learning' when none is present
|
|
201
|
+
*/
|
|
202
|
+
export function logEntryCategory(body) {
|
|
203
|
+
const m = body.match(/^\s*(?:\*\*[^*]+\*\*\s*)?[([]([a-z_-]+)[)\]]/i);
|
|
204
|
+
return m ? m[1].toLowerCase() : 'learning';
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Topic of an entry for grouping in a digest: the first `[[Entity]]` link,
|
|
208
|
+
* else a bold `**Title**` lead, else the category.
|
|
209
|
+
*
|
|
210
|
+
* @param body - Entry body
|
|
211
|
+
* @returns Short topic label
|
|
212
|
+
*/
|
|
213
|
+
export function logEntryTopic(body) {
|
|
214
|
+
const link = body.match(/\[\[([^\]]{1,80})\]\]/);
|
|
215
|
+
if (link)
|
|
216
|
+
return link[1].trim();
|
|
217
|
+
const bold = body.match(/^\s*(?:\([a-z_-]+\)\s*)?\*\*([^*]{1,80})\*\*/i);
|
|
218
|
+
if (bold)
|
|
219
|
+
return bold[1].trim();
|
|
220
|
+
return logEntryCategory(body);
|
|
221
|
+
}
|
|
222
|
+
//# sourceMappingURL=wiki-log-entries.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wiki-log-entries.js","sourceRoot":"","sources":["../../../../../../backend/src/services/wiki/wiki-log-entries.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WikiLogRotationService — keeps a vault's `llm-curated/log.md` readable.
|
|
3
|
+
*
|
|
4
|
+
* The log is append-only and was never rotated: one project vault reached
|
|
5
|
+
* 19 MB / 150k lines, most of it templated noise (#1345). When a log is
|
|
6
|
+
* larger than `ROTATE_MAX_BYTES` or holds more than `ROTATE_MAX_ENTRIES`
|
|
7
|
+
* entries, this service:
|
|
8
|
+
*
|
|
9
|
+
* 1. moves the file, unchanged, to `llm-curated/log-archive/log-<date>.md`
|
|
10
|
+
* (a second rotation on the same day gets a `-2`, `-3`… suffix);
|
|
11
|
+
* 2. writes a fresh `log.md` with the standard header and the non-noise,
|
|
12
|
+
* deduped entries of the last `CARRY_FORWARD_DAYS` days (capped), so
|
|
13
|
+
* search and the digest still see recent learnings.
|
|
14
|
+
*
|
|
15
|
+
* Nothing is deleted. `dryRun` reports what would happen without touching
|
|
16
|
+
* the disk. Walkers skip the archive folder.
|
|
17
|
+
*
|
|
18
|
+
* @module services/wiki/wiki-log-rotation.service
|
|
19
|
+
*/
|
|
20
|
+
import { WikiIngestService } from './wiki-ingest.service.js';
|
|
21
|
+
/** Options for {@link WikiLogRotationService.rotate}. */
|
|
22
|
+
export interface WikiLogRotateOptions {
|
|
23
|
+
/** Report only; write nothing. */
|
|
24
|
+
dryRun?: boolean;
|
|
25
|
+
/** Clock (tests). */
|
|
26
|
+
now?: number;
|
|
27
|
+
/** Size cap override (tests). */
|
|
28
|
+
maxBytes?: number;
|
|
29
|
+
/** Entry-count cap override (tests). */
|
|
30
|
+
maxEntries?: number;
|
|
31
|
+
}
|
|
32
|
+
/** Outcome of one vault's rotation check. */
|
|
33
|
+
export interface WikiLogRotateResult {
|
|
34
|
+
vaultPath: string;
|
|
35
|
+
/** False when the log is missing or under both caps. */
|
|
36
|
+
rotated: boolean;
|
|
37
|
+
/** Why nothing happened (when `rotated` is false). */
|
|
38
|
+
reason?: 'no_log' | 'under_caps';
|
|
39
|
+
/** Log size before rotation. */
|
|
40
|
+
bytes: number;
|
|
41
|
+
/** Entries before rotation. */
|
|
42
|
+
entries: number;
|
|
43
|
+
/** Entries carried into the fresh log. */
|
|
44
|
+
carried: number;
|
|
45
|
+
/** Vault-relative archive path (set when rotated, or planned in a dry run). */
|
|
46
|
+
archivePath?: string;
|
|
47
|
+
dryRun: boolean;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Rotates oversized vault logs into an archive folder. Stateless singleton.
|
|
51
|
+
*/
|
|
52
|
+
export declare class WikiLogRotationService {
|
|
53
|
+
private readonly ingest;
|
|
54
|
+
private static instance;
|
|
55
|
+
private readonly logger;
|
|
56
|
+
constructor(ingest?: WikiIngestService);
|
|
57
|
+
static getInstance(): WikiLogRotationService;
|
|
58
|
+
/** Test-only reset. */
|
|
59
|
+
static _resetForTesting(): void;
|
|
60
|
+
/**
|
|
61
|
+
* Check one vault's log and rotate it when it is over a cap.
|
|
62
|
+
*
|
|
63
|
+
* @param vaultPath - Vault root (must contain `llm-curated/`)
|
|
64
|
+
* @param opts - Dry run, clock and cap overrides
|
|
65
|
+
* @returns What happened (or would happen)
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```typescript
|
|
69
|
+
* const plan = await WikiLogRotationService.getInstance().rotate(vault, { dryRun: true });
|
|
70
|
+
* if (plan.rotated) console.log(`would archive ${plan.bytes} bytes to ${plan.archivePath}`);
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
rotate(vaultPath: string, opts?: WikiLogRotateOptions): Promise<WikiLogRotateResult>;
|
|
74
|
+
/**
|
|
75
|
+
* Rotate every vault in a list; failures are logged per vault and never
|
|
76
|
+
* stop the pass.
|
|
77
|
+
*
|
|
78
|
+
* @param vaults - Vault roots
|
|
79
|
+
* @param opts - Passed to {@link rotate}
|
|
80
|
+
* @returns One result per vault that was checked
|
|
81
|
+
*/
|
|
82
|
+
rotateAll(vaults: readonly string[], opts?: WikiLogRotateOptions): Promise<WikiLogRotateResult[]>;
|
|
83
|
+
/**
|
|
84
|
+
* Vault-relative archive path for a rotation at `now`: `log-YYYY-MM-DD.md`,
|
|
85
|
+
* with a numeric suffix when that name is taken.
|
|
86
|
+
*
|
|
87
|
+
* @param vaultPath - Vault root
|
|
88
|
+
* @param now - Epoch ms
|
|
89
|
+
* @returns Relative path under the archive folder
|
|
90
|
+
*/
|
|
91
|
+
private archivePathFor;
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=wiki-log-rotation.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wiki-log-rotation.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/wiki/wiki-log-rotation.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAQH,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,yDAAyD;AACzD,MAAM,WAAW,oBAAoB;IACnC,kCAAkC;IAClC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,qBAAqB;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wCAAwC;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,6CAA6C;AAC7C,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,OAAO,EAAE,OAAO,CAAC;IACjB,sDAAsD;IACtD,MAAM,CAAC,EAAE,QAAQ,GAAG,YAAY,CAAC;IACjC,gCAAgC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,+BAA+B;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,0CAA0C;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,+EAA+E;IAC/E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,qBAAa,sBAAsB;IAIrB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAHnC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAuC;IAC9D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;gBAEZ,MAAM,GAAE,iBAAmD;IAIxF,MAAM,CAAC,WAAW,IAAI,sBAAsB;IAK5C,uBAAuB;IACvB,MAAM,CAAC,gBAAgB,IAAI,IAAI;IAI/B;;;;;;;;;;;;OAYG;IACG,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,GAAE,oBAAyB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAgD9F;;;;;;;OAOG;IACG,SAAS,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,GAAE,oBAAyB,GAAG,OAAO,CAAC,mBAAmB,EAAE,CAAC;IAY3G;;;;;;;OAOG;IACH,OAAO,CAAC,cAAc;CAQvB"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WikiLogRotationService — keeps a vault's `llm-curated/log.md` readable.
|
|
3
|
+
*
|
|
4
|
+
* The log is append-only and was never rotated: one project vault reached
|
|
5
|
+
* 19 MB / 150k lines, most of it templated noise (#1345). When a log is
|
|
6
|
+
* larger than `ROTATE_MAX_BYTES` or holds more than `ROTATE_MAX_ENTRIES`
|
|
7
|
+
* entries, this service:
|
|
8
|
+
*
|
|
9
|
+
* 1. moves the file, unchanged, to `llm-curated/log-archive/log-<date>.md`
|
|
10
|
+
* (a second rotation on the same day gets a `-2`, `-3`… suffix);
|
|
11
|
+
* 2. writes a fresh `log.md` with the standard header and the non-noise,
|
|
12
|
+
* deduped entries of the last `CARRY_FORWARD_DAYS` days (capped), so
|
|
13
|
+
* search and the digest still see recent learnings.
|
|
14
|
+
*
|
|
15
|
+
* Nothing is deleted. `dryRun` reports what would happen without touching
|
|
16
|
+
* the disk. Walkers skip the archive folder.
|
|
17
|
+
*
|
|
18
|
+
* @module services/wiki/wiki-log-rotation.service
|
|
19
|
+
*/
|
|
20
|
+
import * as path from 'path';
|
|
21
|
+
import * as fs from 'fs/promises';
|
|
22
|
+
import { existsSync } from 'fs';
|
|
23
|
+
import { LoggerService } from '../core/logger.service.js';
|
|
24
|
+
import { WIKI_LOG_CONSTANTS } from '../../constants.js';
|
|
25
|
+
import { WIKI_LOG_HEADER, parseLogEntries, recentContentEntries, serializeLogEntry } from './wiki-log-entries.js';
|
|
26
|
+
import { WikiIngestService } from './wiki-ingest.service.js';
|
|
27
|
+
/**
|
|
28
|
+
* Rotates oversized vault logs into an archive folder. Stateless singleton.
|
|
29
|
+
*/
|
|
30
|
+
export class WikiLogRotationService {
|
|
31
|
+
ingest;
|
|
32
|
+
static instance = null;
|
|
33
|
+
logger;
|
|
34
|
+
constructor(ingest = WikiIngestService.getInstance()) {
|
|
35
|
+
this.ingest = ingest;
|
|
36
|
+
this.logger = LoggerService.getInstance().createComponentLogger('WikiLogRotation');
|
|
37
|
+
}
|
|
38
|
+
static getInstance() {
|
|
39
|
+
if (!this.instance)
|
|
40
|
+
this.instance = new WikiLogRotationService();
|
|
41
|
+
return this.instance;
|
|
42
|
+
}
|
|
43
|
+
/** Test-only reset. */
|
|
44
|
+
static _resetForTesting() {
|
|
45
|
+
this.instance = null;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Check one vault's log and rotate it when it is over a cap.
|
|
49
|
+
*
|
|
50
|
+
* @param vaultPath - Vault root (must contain `llm-curated/`)
|
|
51
|
+
* @param opts - Dry run, clock and cap overrides
|
|
52
|
+
* @returns What happened (or would happen)
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* const plan = await WikiLogRotationService.getInstance().rotate(vault, { dryRun: true });
|
|
57
|
+
* if (plan.rotated) console.log(`would archive ${plan.bytes} bytes to ${plan.archivePath}`);
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
async rotate(vaultPath, opts = {}) {
|
|
61
|
+
const dryRun = opts.dryRun === true;
|
|
62
|
+
const now = opts.now ?? Date.now();
|
|
63
|
+
const maxBytes = opts.maxBytes ?? WIKI_LOG_CONSTANTS.ROTATE_MAX_BYTES;
|
|
64
|
+
const maxEntries = opts.maxEntries ?? WIKI_LOG_CONSTANTS.ROTATE_MAX_ENTRIES;
|
|
65
|
+
const logAbs = path.join(vaultPath, WIKI_LOG_CONSTANTS.LOG_RELATIVE_PATH);
|
|
66
|
+
const base = { vaultPath, rotated: false, bytes: 0, entries: 0, carried: 0, dryRun };
|
|
67
|
+
let size;
|
|
68
|
+
try {
|
|
69
|
+
size = (await fs.stat(logAbs)).size;
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return { ...base, reason: 'no_log' };
|
|
73
|
+
}
|
|
74
|
+
base.bytes = size;
|
|
75
|
+
const raw = await fs.readFile(logAbs, 'utf8');
|
|
76
|
+
const entries = parseLogEntries(raw);
|
|
77
|
+
base.entries = entries.length;
|
|
78
|
+
if (size <= maxBytes && entries.length <= maxEntries)
|
|
79
|
+
return { ...base, reason: 'under_caps' };
|
|
80
|
+
// Handover snapshots are carried: an agent may still be pointed at one.
|
|
81
|
+
const carried = recentContentEntries(entries, WIKI_LOG_CONSTANTS.CARRY_FORWARD_DAYS, now, WIKI_LOG_CONSTANTS.CARRY_FORWARD_MAX_ENTRIES, { includeHandovers: true })
|
|
82
|
+
// Oldest first in the fresh file, like any log.
|
|
83
|
+
.sort((a, b) => a.timestampMs - b.timestampMs);
|
|
84
|
+
const archiveRel = this.archivePathFor(vaultPath, now);
|
|
85
|
+
const result = { ...base, rotated: true, carried: carried.length, archivePath: archiveRel };
|
|
86
|
+
if (dryRun) {
|
|
87
|
+
this.logger.info('WikiLogRotation dry run — would rotate', { vaultPath, bytes: size, entries: base.entries, carried: carried.length, archivePath: archiveRel });
|
|
88
|
+
return result;
|
|
89
|
+
}
|
|
90
|
+
const archiveAbs = path.join(vaultPath, archiveRel);
|
|
91
|
+
await fs.mkdir(path.dirname(archiveAbs), { recursive: true });
|
|
92
|
+
// Move first (atomic on one filesystem), then write the fresh log. A
|
|
93
|
+
// crash in between leaves no log.md, which the next append recreates;
|
|
94
|
+
// nothing is lost because the archive already holds everything.
|
|
95
|
+
await fs.rename(logAbs, archiveAbs);
|
|
96
|
+
const fresh = WIKI_LOG_HEADER + `\n<!-- rotated ${new Date(now).toISOString()}: ${base.entries} entries archived to ${archiveRel}; ${carried.length} recent entries carried forward -->\n` + carried.map((e) => serializeLogEntry(e)).join('');
|
|
97
|
+
const tmp = `${logAbs}.tmp`;
|
|
98
|
+
await fs.writeFile(tmp, fresh, 'utf8');
|
|
99
|
+
await fs.rename(tmp, logAbs);
|
|
100
|
+
this.ingest.forgetRecentBodies(logAbs);
|
|
101
|
+
this.logger.info('WikiLogRotation rotated log', { vaultPath, bytes: size, entries: base.entries, carried: carried.length, archivePath: archiveRel });
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Rotate every vault in a list; failures are logged per vault and never
|
|
106
|
+
* stop the pass.
|
|
107
|
+
*
|
|
108
|
+
* @param vaults - Vault roots
|
|
109
|
+
* @param opts - Passed to {@link rotate}
|
|
110
|
+
* @returns One result per vault that was checked
|
|
111
|
+
*/
|
|
112
|
+
async rotateAll(vaults, opts = {}) {
|
|
113
|
+
const out = [];
|
|
114
|
+
for (const vaultPath of vaults) {
|
|
115
|
+
try {
|
|
116
|
+
out.push(await this.rotate(vaultPath, opts));
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
this.logger.warn('WikiLogRotation failed for vault (non-fatal)', { vaultPath, error: err instanceof Error ? err.message : String(err) });
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return out;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Vault-relative archive path for a rotation at `now`: `log-YYYY-MM-DD.md`,
|
|
126
|
+
* with a numeric suffix when that name is taken.
|
|
127
|
+
*
|
|
128
|
+
* @param vaultPath - Vault root
|
|
129
|
+
* @param now - Epoch ms
|
|
130
|
+
* @returns Relative path under the archive folder
|
|
131
|
+
*/
|
|
132
|
+
archivePathFor(vaultPath, now) {
|
|
133
|
+
const day = new Date(now).toISOString().slice(0, 10);
|
|
134
|
+
for (let n = 1;; n++) {
|
|
135
|
+
const name = n === 1 ? `log-${day}.md` : `log-${day}-${n}.md`;
|
|
136
|
+
const rel = `${WIKI_LOG_CONSTANTS.ARCHIVE_DIR}/${name}`;
|
|
137
|
+
if (!existsSync(path.join(vaultPath, rel)))
|
|
138
|
+
return rel;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=wiki-log-rotation.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wiki-log-rotation.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/wiki/wiki-log-rotation.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WikiMaintenanceService — the scheduler behind log hygiene (#1345).
|
|
3
|
+
*
|
|
4
|
+
* One hourly tick:
|
|
5
|
+
* - every tick: a queue drain pass ({@link WikiQueueDrainService});
|
|
6
|
+
* - once per day (and on the first tick after boot when the last daily
|
|
7
|
+
* pass is older than a day): log rotation then digest compile for every
|
|
8
|
+
* discovered vault.
|
|
9
|
+
*
|
|
10
|
+
* The first tick runs `MAINTENANCE_BOOT_DELAY_MS` after `start()` so boot
|
|
11
|
+
* I/O settles first. State (last daily pass) lives in
|
|
12
|
+
* `CREWLY_HOME/wiki-maintenance-state.json`. `CREWLY_WIKI_MAINTENANCE=false`
|
|
13
|
+
* disables the whole thing. Every step is non-fatal and logged.
|
|
14
|
+
*
|
|
15
|
+
* @module services/wiki/wiki-maintenance.service
|
|
16
|
+
*/
|
|
17
|
+
import { WikiLogRotationService, type WikiLogRotateResult } from './wiki-log-rotation.service.js';
|
|
18
|
+
import { WikiLogCompileService, type WikiLogCompileResult } from './wiki-log-compile.service.js';
|
|
19
|
+
import { WikiQueueDrainService, type WikiQueueDrainResult } from './wiki-queue-drain.service.js';
|
|
20
|
+
/** Options for {@link WikiMaintenanceService}. */
|
|
21
|
+
export interface WikiMaintenanceOptions {
|
|
22
|
+
/** Tick interval (default hourly). */
|
|
23
|
+
intervalMs?: number;
|
|
24
|
+
/** Gap between daily passes (default 24 h). */
|
|
25
|
+
dailyMs?: number;
|
|
26
|
+
/** Delay before the first tick (default 90 s; 0 = immediate). */
|
|
27
|
+
bootDelayMs?: number;
|
|
28
|
+
/** State file (default under CREWLY_HOME). `null` keeps state in memory (tests). */
|
|
29
|
+
statePath?: string | null;
|
|
30
|
+
/** Vault discovery override (tests). */
|
|
31
|
+
discoverRoots?: () => Promise<string[]>;
|
|
32
|
+
/** Service overrides (tests). */
|
|
33
|
+
rotation?: WikiLogRotationService;
|
|
34
|
+
compile?: WikiLogCompileService;
|
|
35
|
+
drain?: WikiQueueDrainService;
|
|
36
|
+
/** Clock (tests). */
|
|
37
|
+
now?: () => number;
|
|
38
|
+
/** Dry run: every step reports and writes nothing. */
|
|
39
|
+
dryRun?: boolean;
|
|
40
|
+
}
|
|
41
|
+
/** Outcome of one tick. */
|
|
42
|
+
export interface WikiMaintenanceTickResult {
|
|
43
|
+
drain: WikiQueueDrainResult | null;
|
|
44
|
+
/** Set when the daily pass ran this tick. */
|
|
45
|
+
daily?: {
|
|
46
|
+
vaults: string[];
|
|
47
|
+
rotated: WikiLogRotateResult[];
|
|
48
|
+
compiled: WikiLogCompileResult[];
|
|
49
|
+
};
|
|
50
|
+
skippedDaily?: 'not_due';
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Hourly wiki maintenance scheduler. Start at boot, stop at shutdown.
|
|
54
|
+
*/
|
|
55
|
+
export declare class WikiMaintenanceService {
|
|
56
|
+
private static instance;
|
|
57
|
+
private readonly logger;
|
|
58
|
+
private readonly intervalMs;
|
|
59
|
+
private readonly dailyMs;
|
|
60
|
+
private readonly bootDelayMs;
|
|
61
|
+
private readonly statePath;
|
|
62
|
+
private readonly discoverRoots;
|
|
63
|
+
private readonly rotation;
|
|
64
|
+
private readonly compile;
|
|
65
|
+
private readonly drain;
|
|
66
|
+
private readonly nowFn;
|
|
67
|
+
private readonly dryRun;
|
|
68
|
+
private timer;
|
|
69
|
+
private bootTimer;
|
|
70
|
+
private running;
|
|
71
|
+
private state;
|
|
72
|
+
private stateLoaded;
|
|
73
|
+
constructor(opts?: WikiMaintenanceOptions);
|
|
74
|
+
static getInstance(): WikiMaintenanceService | null;
|
|
75
|
+
/** Wire / detach the production singleton. */
|
|
76
|
+
static setInstance(next: WikiMaintenanceService | null): void;
|
|
77
|
+
/**
|
|
78
|
+
* Begin ticking. Idempotent. Returns false when the kill switch is set.
|
|
79
|
+
*
|
|
80
|
+
* @returns Whether the scheduler started
|
|
81
|
+
*/
|
|
82
|
+
start(): boolean;
|
|
83
|
+
/** Stop ticking. Safe to call more than once. */
|
|
84
|
+
stop(): void;
|
|
85
|
+
/**
|
|
86
|
+
* Whether the daily pass is due.
|
|
87
|
+
*
|
|
88
|
+
* @returns True when no daily pass is recorded or it is older than `dailyMs`
|
|
89
|
+
*/
|
|
90
|
+
isDailyDue(): boolean;
|
|
91
|
+
/**
|
|
92
|
+
* One tick: drain, then the daily pass when due. Public for tests and
|
|
93
|
+
* an on-demand run.
|
|
94
|
+
*
|
|
95
|
+
* @param opts - `force` runs the daily pass whether or not it is due
|
|
96
|
+
* @returns What ran
|
|
97
|
+
*/
|
|
98
|
+
tick(opts?: {
|
|
99
|
+
force?: boolean;
|
|
100
|
+
}): Promise<WikiMaintenanceTickResult>;
|
|
101
|
+
private loadState;
|
|
102
|
+
private saveState;
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=wiki-maintenance.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wiki-maintenance.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/wiki/wiki-maintenance.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAQH,OAAO,EAAE,sBAAsB,EAAE,KAAK,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAClG,OAAO,EAAE,qBAAqB,EAAE,KAAK,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACjG,OAAO,EAAE,qBAAqB,EAAE,KAAK,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAQjG,kDAAkD;AAClD,MAAM,WAAW,sBAAsB;IACrC,sCAAsC;IACtC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+CAA+C;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oFAAoF;IACpF,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,wCAAwC;IACxC,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACxC,iCAAiC;IACjC,QAAQ,CAAC,EAAE,sBAAsB,CAAC;IAClC,OAAO,CAAC,EAAE,qBAAqB,CAAC;IAChC,KAAK,CAAC,EAAE,qBAAqB,CAAC;IAC9B,qBAAqB;IACrB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,sDAAsD;IACtD,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,2BAA2B;AAC3B,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACnC,6CAA6C;IAC7C,KAAK,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,OAAO,EAAE,mBAAmB,EAAE,CAAC;QAAC,QAAQ,EAAE,oBAAoB,EAAE,CAAA;KAAE,CAAC;IAC/F,YAAY,CAAC,EAAE,SAAS,CAAC;CAC1B;AAED;;GAEG;AACH,qBAAa,sBAAsB;IACjC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAuC;IAC9D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgB;IAC1C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA0B;IACxD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAyB;IAClD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwB;IAChD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAwB;IAC9C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;IACjC,OAAO,CAAC,KAAK,CAA+B;IAC5C,OAAO,CAAC,SAAS,CAA+B;IAChD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,KAAK,CAA2C;IACxD,OAAO,CAAC,WAAW,CAAS;gBAEhB,IAAI,GAAE,sBAA2B;IAc7C,MAAM,CAAC,WAAW,IAAI,sBAAsB,GAAG,IAAI;IAInD,8CAA8C;IAC9C,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,sBAAsB,GAAG,IAAI,GAAG,IAAI;IAK7D;;;;OAIG;IACH,KAAK,IAAI,OAAO;IAiBhB,iDAAiD;IACjD,IAAI,IAAI,IAAI;IAYZ;;;;OAIG;IACH,UAAU,IAAI,OAAO;IAMrB;;;;;;OAMG;IACG,IAAI,CAAC,IAAI,GAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,OAAO,CAAC,yBAAyB,CAAC;YA2ChE,SAAS;YAYT,SAAS;CASxB"}
|