mirror-mind 0.0.1 → 0.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/hooks/log-assistant-reply.sh +85 -0
- package/.claude/hooks/log-session-end.sh +85 -0
- package/.claude/hooks/log-user-prompt.sh +85 -0
- package/.claude/hooks/mirror-inject.sh +85 -0
- package/.claude/hooks/session-start.sh +85 -0
- package/.gemini/hooks/log-assistant.sh +85 -0
- package/.gemini/hooks/log-user.sh +85 -0
- package/.gemini/hooks/session-end.sh +85 -0
- package/.gemini/hooks/session-start.sh +85 -0
- package/.pi/extensions/mirror-logger.ts +646 -0
- package/.pi/skills/mm-backup/SKILL.md +21 -0
- package/.pi/skills/mm-build/SKILL.md +1206 -0
- package/.pi/skills/mm-consolidate/SKILL.md +112 -0
- package/.pi/skills/mm-consult/SKILL.md +70 -0
- package/.pi/skills/mm-conversations/SKILL.md +16 -0
- package/.pi/skills/mm-discard/SKILL.md +39 -0
- package/.pi/skills/mm-explore/SKILL.md +255 -0
- package/.pi/skills/mm-help/SKILL.md +74 -0
- package/.pi/skills/mm-identity/SKILL.md +96 -0
- package/.pi/skills/mm-journal/SKILL.md +16 -0
- package/.pi/skills/mm-journey/SKILL.md +23 -0
- package/.pi/skills/mm-journeys/SKILL.md +15 -0
- package/.pi/skills/mm-memories/SKILL.md +17 -0
- package/.pi/skills/mm-mirror/SKILL.md +98 -0
- package/.pi/skills/mm-mute/SKILL.md +18 -0
- package/.pi/skills/mm-new/SKILL.md +18 -0
- package/.pi/skills/mm-recall/SKILL.md +17 -0
- package/.pi/skills/mm-release-notes/SKILL.md +52 -0
- package/.pi/skills/mm-seed/SKILL.md +19 -0
- package/.pi/skills/mm-shadow/SKILL.md +117 -0
- package/.pi/skills/mm-soul/SKILL.md +502 -0
- package/.pi/skills/mm-tasks/SKILL.md +24 -0
- package/.pi/skills/mm-update/SKILL.md +32 -0
- package/.pi/skills/mm-week/SKILL.md +28 -0
- package/.pi/skills/mm-welcome/SKILL.md +24 -0
- package/AGENTS.md +188 -0
- package/README.md +126 -9
- package/bin/loader.js +67 -0
- package/bin/mirror-hook.js +7 -0
- package/bin/mirror.js +7 -0
- package/docs/releases/index.md +100 -0
- package/docs/releases/pending-cutoffs.md +510 -0
- package/docs/releases/v0.10.0.md +123 -0
- package/docs/releases/v0.10.1.md +66 -0
- package/docs/releases/v0.10.10.md +51 -0
- package/docs/releases/v0.10.11.md +39 -0
- package/docs/releases/v0.10.12.md +57 -0
- package/docs/releases/v0.10.13.md +35 -0
- package/docs/releases/v0.10.14.md +42 -0
- package/docs/releases/v0.10.15.md +53 -0
- package/docs/releases/v0.10.16.md +35 -0
- package/docs/releases/v0.10.17.md +43 -0
- package/docs/releases/v0.10.2.md +64 -0
- package/docs/releases/v0.10.3.md +78 -0
- package/docs/releases/v0.10.4.md +42 -0
- package/docs/releases/v0.10.5.md +57 -0
- package/docs/releases/v0.10.6.md +47 -0
- package/docs/releases/v0.10.7.md +53 -0
- package/docs/releases/v0.10.8.md +49 -0
- package/docs/releases/v0.10.9.md +37 -0
- package/docs/releases/v0.11.0.md +86 -0
- package/docs/releases/v0.12.0.md +67 -0
- package/docs/releases/v0.13.0.md +64 -0
- package/docs/releases/v0.14.0.md +68 -0
- package/docs/releases/v0.15.0.md +48 -0
- package/docs/releases/v0.16.0.md +50 -0
- package/docs/releases/v0.16.1.md +55 -0
- package/docs/releases/v0.16.2.md +36 -0
- package/docs/releases/v0.17.0.md +50 -0
- package/docs/releases/v0.17.1.md +58 -0
- package/docs/releases/v0.17.2.md +42 -0
- package/docs/releases/v0.17.3.md +58 -0
- package/docs/releases/v0.18.0.md +84 -0
- package/docs/releases/v0.18.1.md +51 -0
- package/docs/releases/v0.18.2.md +69 -0
- package/docs/releases/v0.19.0.md +85 -0
- package/docs/releases/v0.19.1.md +46 -0
- package/docs/releases/v0.20.0.md +85 -0
- package/docs/releases/v0.21.0.md +61 -0
- package/docs/releases/v0.21.1.md +47 -0
- package/docs/releases/v0.22.0.md +77 -0
- package/docs/releases/v0.22.1.md +42 -0
- package/docs/releases/v0.23.0.md +105 -0
- package/docs/releases/v0.24.0.md +125 -0
- package/docs/releases/v0.25.0.md +107 -0
- package/docs/releases/v0.26.0.md +139 -0
- package/docs/releases/v0.26.1.md +65 -0
- package/docs/releases/v0.26.2.md +43 -0
- package/docs/releases/v0.27.0.md +63 -0
- package/docs/releases/v0.28.0.md +59 -0
- package/docs/releases/v0.29.0.md +61 -0
- package/docs/releases/v0.29.1.md +59 -0
- package/docs/releases/v0.29.2.md +59 -0
- package/docs/releases/v0.29.3.md +93 -0
- package/docs/releases/v0.30.0.md +75 -0
- package/docs/releases/v0.30.1.md +93 -0
- package/docs/releases/v0.30.2.md +66 -0
- package/docs/releases/v0.31.0.md +122 -0
- package/docs/releases/v0.31.1.md +142 -0
- package/docs/releases/v0.31.10.md +118 -0
- package/docs/releases/v0.31.11.md +88 -0
- package/docs/releases/v0.31.12.md +105 -0
- package/docs/releases/v0.31.13.md +99 -0
- package/docs/releases/v0.31.14.md +97 -0
- package/docs/releases/v0.31.2.md +115 -0
- package/docs/releases/v0.31.3.md +142 -0
- package/docs/releases/v0.31.4.md +117 -0
- package/docs/releases/v0.31.5.md +155 -0
- package/docs/releases/v0.31.6.md +132 -0
- package/docs/releases/v0.31.7.md +132 -0
- package/docs/releases/v0.31.8.md +120 -0
- package/docs/releases/v0.31.9.md +120 -0
- package/docs/releases/v0.32.0.md +261 -0
- package/docs/releases/v0.32.1.md +59 -0
- package/docs/releases/v0.33.0.md +164 -0
- package/docs/releases/v0.8.0.md +118 -0
- package/docs/releases/v0.9.0.md +98 -0
- package/docs/releases/v0.9.1.md +83 -0
- package/package.json +102 -6
- package/plugins/mirror-mind/.claude-plugin/plugin.json +17 -0
- package/plugins/mirror-mind/hooks/hooks.json +62 -0
- package/plugins/mirror-mind/hooks/log-assistant-reply.sh +98 -0
- package/plugins/mirror-mind/hooks/log-session-end.sh +98 -0
- package/plugins/mirror-mind/hooks/log-user-prompt.sh +98 -0
- package/plugins/mirror-mind/hooks/mirror-inject.sh +98 -0
- package/plugins/mirror-mind/hooks/session-start.sh +98 -0
- package/plugins/mirror-mind/skills/mm-backup/SKILL.md +27 -0
- package/plugins/mirror-mind/skills/mm-build/SKILL.md +1206 -0
- package/plugins/mirror-mind/skills/mm-consolidate/SKILL.md +112 -0
- package/plugins/mirror-mind/skills/mm-consult/SKILL.md +83 -0
- package/plugins/mirror-mind/skills/mm-conversations/SKILL.md +17 -0
- package/plugins/mirror-mind/skills/mm-discard/SKILL.md +40 -0
- package/plugins/mirror-mind/skills/mm-explore/SKILL.md +241 -0
- package/plugins/mirror-mind/skills/mm-help/SKILL.md +104 -0
- package/plugins/mirror-mind/skills/mm-identity/SKILL.md +96 -0
- package/plugins/mirror-mind/skills/mm-journal/SKILL.md +21 -0
- package/plugins/mirror-mind/skills/mm-journey/SKILL.md +37 -0
- package/plugins/mirror-mind/skills/mm-journeys/SKILL.md +15 -0
- package/plugins/mirror-mind/skills/mm-memories/SKILL.md +20 -0
- package/plugins/mirror-mind/skills/mm-mirror/SKILL.md +67 -0
- package/plugins/mirror-mind/skills/mm-mute/SKILL.md +18 -0
- package/plugins/mirror-mind/skills/mm-new/SKILL.md +18 -0
- package/plugins/mirror-mind/skills/mm-recall/SKILL.md +17 -0
- package/plugins/mirror-mind/skills/mm-release-notes/SKILL.md +31 -0
- package/plugins/mirror-mind/skills/mm-seed/SKILL.md +15 -0
- package/plugins/mirror-mind/skills/mm-shadow/SKILL.md +117 -0
- package/plugins/mirror-mind/skills/mm-soul/SKILL.md +488 -0
- package/plugins/mirror-mind/skills/mm-tasks/SKILL.md +36 -0
- package/plugins/mirror-mind/skills/mm-update/SKILL.md +30 -0
- package/plugins/mirror-mind/skills/mm-week/SKILL.md +46 -0
- package/plugins/mirror-mind/skills/mm-welcome/SKILL.md +22 -0
- package/scripts/codex-hooks/session-end.sh +85 -0
- package/scripts/codex-hooks/session-start.sh +85 -0
- package/scripts/codex-mirror.sh +48 -0
- package/templates/identity/README.md +119 -0
- package/templates/identity/ego/behavior.yaml +52 -0
- package/templates/identity/ego/constraints.yaml +15 -0
- package/templates/identity/ego/identity.yaml +43 -0
- package/templates/identity/journeys/personal-growth.yaml +39 -0
- package/templates/identity/organization/identity.yaml +24 -0
- package/templates/identity/organization/principles.yaml +17 -0
- package/templates/identity/personas/coach.yaml +94 -0
- package/templates/identity/personas/designer.yaml +93 -0
- package/templates/identity/personas/doctor.yaml +96 -0
- package/templates/identity/personas/engineer.yaml +77 -0
- package/templates/identity/personas/financial.yaml +97 -0
- package/templates/identity/personas/prompt-engineer.yaml +122 -0
- package/templates/identity/personas/researcher.yaml +88 -0
- package/templates/identity/personas/strategist.yaml +91 -0
- package/templates/identity/personas/teacher.yaml +95 -0
- package/templates/identity/personas/therapist.yaml +91 -0
- package/templates/identity/personas/thinker.yaml +74 -0
- package/templates/identity/personas/writer.yaml +76 -0
- package/templates/identity/self/config.yaml +16 -0
- package/templates/identity/self/soul.yaml +105 -0
- package/templates/identity/user/identity.yaml +30 -0
- package/ts/src/backup/staging.ts +62 -0
- package/ts/src/backup/zipBackup.ts +267 -0
- package/ts/src/backup/zipReader.ts +109 -0
- package/ts/src/backup/zipWriter.ts +148 -0
- package/ts/src/builder/activeCheckpoint.ts +134 -0
- package/ts/src/builder/aggregateStatus.ts +34 -0
- package/ts/src/builder/approve.ts +149 -0
- package/ts/src/builder/argv.ts +292 -0
- package/ts/src/builder/ariadMethod.ts +536 -0
- package/ts/src/builder/artifacts/artifactSurfaces.ts +106 -0
- package/ts/src/builder/artifacts/artifactWriter.ts +113 -0
- package/ts/src/builder/artifacts/closureArtifacts.ts +199 -0
- package/ts/src/builder/artifacts/deliveryStoryArtifacts.ts +316 -0
- package/ts/src/builder/artifacts/planArtifacts.ts +242 -0
- package/ts/src/builder/artifacts/scaffoldSections.ts +273 -0
- package/ts/src/builder/artifacts/scaffoldState.ts +227 -0
- package/ts/src/builder/artifacts/storyFiles.ts +61 -0
- package/ts/src/builder/artifacts/storyIndex.ts +166 -0
- package/ts/src/builder/cadence.ts +59 -0
- package/ts/src/builder/card.ts +192 -0
- package/ts/src/builder/checkpointRefused.ts +66 -0
- package/ts/src/builder/closure.ts +964 -0
- package/ts/src/builder/commands.ts +2053 -0
- package/ts/src/builder/cursorPosition.ts +176 -0
- package/ts/src/builder/cursorTransitions.ts +77 -0
- package/ts/src/builder/deliveryCursor.ts +577 -0
- package/ts/src/builder/deliveryStoryClosure.ts +521 -0
- package/ts/src/builder/deliveryStoryPlan.ts +536 -0
- package/ts/src/builder/deliveryStoryReady.ts +160 -0
- package/ts/src/builder/deliveryStoryRoadmapClosure.ts +151 -0
- package/ts/src/builder/expand.ts +336 -0
- package/ts/src/builder/flowUnit.ts +339 -0
- package/ts/src/builder/homeSurface.ts +122 -0
- package/ts/src/builder/implementationGuard.ts +125 -0
- package/ts/src/builder/index.ts +11 -0
- package/ts/src/builder/lifecycleRefusal.ts +92 -0
- package/ts/src/builder/lifecycleRibbon.ts +159 -0
- package/ts/src/builder/load.ts +313 -0
- package/ts/src/builder/methodAdoption.ts +113 -0
- package/ts/src/builder/methodDefinition.ts +429 -0
- package/ts/src/builder/methodInspection.ts +371 -0
- package/ts/src/builder/plan.ts +408 -0
- package/ts/src/builder/planPreauthorization.ts +265 -0
- package/ts/src/builder/prepare.ts +225 -0
- package/ts/src/builder/projectPaths.ts +64 -0
- package/ts/src/builder/pull.ts +356 -0
- package/ts/src/builder/pullCandidates.ts +463 -0
- package/ts/src/builder/pullCandidatesRender.ts +238 -0
- package/ts/src/builder/refinementField.ts +93 -0
- package/ts/src/builder/releaseIntent.ts +173 -0
- package/ts/src/builder/resumeState.ts +84 -0
- package/ts/src/builder/resumeSurface.ts +149 -0
- package/ts/src/builder/roadmapGrammar.ts +300 -0
- package/ts/src/builder/roadmapScan.ts +97 -0
- package/ts/src/builder/roadmapScope.ts +210 -0
- package/ts/src/builder/scopePhrases.ts +146 -0
- package/ts/src/builder/storyPaths.ts +196 -0
- package/ts/src/builder/storyPlanPreauthorization.ts +287 -0
- package/ts/src/builder/surfaceProtocol.ts +42 -0
- package/ts/src/builder/templateGeneration.ts +148 -0
- package/ts/src/builder/transition.ts +178 -0
- package/ts/src/consult/args.ts +99 -0
- package/ts/src/consult/core.ts +122 -0
- package/ts/src/consult/modelCatalog.ts +55 -0
- package/ts/src/consult/render.ts +47 -0
- package/ts/src/conversation/append.ts +414 -0
- package/ts/src/conversation/backfill.ts +387 -0
- package/ts/src/conversation/closeTail.ts +467 -0
- package/ts/src/conversation/extraction.ts +333 -0
- package/ts/src/conversation/extractionDriver.ts +130 -0
- package/ts/src/conversation/extractionRun.ts +70 -0
- package/ts/src/conversation/hookPayload.ts +51 -0
- package/ts/src/conversation/journeyInference.ts +165 -0
- package/ts/src/conversation/journeyRepair.ts +114 -0
- package/ts/src/conversation/lifecycleFaces.ts +197 -0
- package/ts/src/conversation/lifecycleWrites.ts +313 -0
- package/ts/src/conversation/listing.ts +77 -0
- package/ts/src/conversation/logger.ts +851 -0
- package/ts/src/conversation/loggerCli.ts +321 -0
- package/ts/src/conversation/loggerRuntime.ts +259 -0
- package/ts/src/conversation/metadataLifecycle.ts +443 -0
- package/ts/src/conversation/recall.ts +66 -0
- package/ts/src/conversation/sessionComposites.ts +258 -0
- package/ts/src/conversation/sessionImport.ts +90 -0
- package/ts/src/conversation/transcriptBackfill.ts +141 -0
- package/ts/src/cultivation/applyActions.ts +241 -0
- package/ts/src/cultivation/cluster.ts +86 -0
- package/ts/src/cultivation/consolidationStore.ts +281 -0
- package/ts/src/cultivation/promptContext.ts +62 -0
- package/ts/src/cultivation/propose.ts +305 -0
- package/ts/src/cultivation/scan.ts +155 -0
- package/ts/src/db/backupGate.ts +47 -0
- package/ts/src/db/bootstrap.ts +108 -0
- package/ts/src/db/bootstrapLock.ts +223 -0
- package/ts/src/db/copyGuard.ts +60 -0
- package/ts/src/db/database.ts +397 -0
- package/ts/src/db/decode.ts +66 -0
- package/ts/src/db/ftsIntegrity.ts +41 -0
- package/ts/src/db/migrateOnOpen.ts +214 -0
- package/ts/src/db/migrations.ts +576 -0
- package/ts/src/db/readyOnOpen.ts +35 -0
- package/ts/src/db/rowDecode.ts +42 -0
- package/ts/src/db/schema.ts +432 -0
- package/ts/src/db/schemaInventory.ts +225 -0
- package/ts/src/db/schemaInventorySnapshot.ts +2107 -0
- package/ts/src/db/schemaState.ts +91 -0
- package/ts/src/db/schemaTsDivergence.ts +114 -0
- package/ts/src/descriptor/descriptorRead.ts +49 -0
- package/ts/src/docs/docsLint.ts +265 -0
- package/ts/src/explorer/handoff.ts +522 -0
- package/ts/src/explorer/render.ts +335 -0
- package/ts/src/explorer/story.ts +769 -0
- package/ts/src/explorer/transition.ts +72 -0
- package/ts/src/extensions/bindings.ts +170 -0
- package/ts/src/extensions/catalog.ts +249 -0
- package/ts/src/extensions/catalogCommands.ts +513 -0
- package/ts/src/extensions/catalogWrites.ts +652 -0
- package/ts/src/extensions/contextRuntime.ts +325 -0
- package/ts/src/extensions/dispatch.ts +374 -0
- package/ts/src/extensions/errors.ts +24 -0
- package/ts/src/extensions/manifest.ts +356 -0
- package/ts/src/extensions/migrations.ts +350 -0
- package/ts/src/extraction/conversation.ts +304 -0
- package/ts/src/extraction/conversationMetadata.ts +206 -0
- package/ts/src/extraction/fencing.ts +106 -0
- package/ts/src/extraction/json.ts +17 -0
- package/ts/src/extraction/prompts.ts +470 -0
- package/ts/src/frontDoor/args.ts +30 -0
- package/ts/src/frontDoor/argvShape.ts +106 -0
- package/ts/src/frontDoor/buildLoadRuntime.ts +139 -0
- package/ts/src/frontDoor/buildRoute.ts +398 -0
- package/ts/src/frontDoor/cli.ts +1872 -0
- package/ts/src/frontDoor/cloneRoleGuard.ts +98 -0
- package/ts/src/frontDoor/consultRoute.ts +50 -0
- package/ts/src/frontDoor/contentTailRoute.ts +239 -0
- package/ts/src/frontDoor/conversationLoggerRoute.ts +83 -0
- package/ts/src/frontDoor/cultivationRoute.ts +210 -0
- package/ts/src/frontDoor/dbPath.ts +131 -0
- package/ts/src/frontDoor/dbSafetyToolsRoute.ts +240 -0
- package/ts/src/frontDoor/exploreRoute.ts +572 -0
- package/ts/src/frontDoor/extensionCatalogRoute.ts +252 -0
- package/ts/src/frontDoor/frontDoorLog.ts +57 -0
- package/ts/src/frontDoor/identityWrite.ts +36 -0
- package/ts/src/frontDoor/journeyWriteRoute.ts +26 -0
- package/ts/src/frontDoor/lifecycleWriteRoute.ts +110 -0
- package/ts/src/frontDoor/liveBackup.ts +100 -0
- package/ts/src/frontDoor/mirrorModeRoute.ts +163 -0
- package/ts/src/frontDoor/namedRefusal.ts +35 -0
- package/ts/src/frontDoor/nodeSupport.ts +24 -0
- package/ts/src/frontDoor/render/consolidate.ts +199 -0
- package/ts/src/frontDoor/render/conversations.ts +33 -0
- package/ts/src/frontDoor/render/cultivationShared.ts +21 -0
- package/ts/src/frontDoor/render/descriptor.ts +20 -0
- package/ts/src/frontDoor/render/detectPersona.ts +50 -0
- package/ts/src/frontDoor/render/icons.ts +13 -0
- package/ts/src/frontDoor/render/identity.ts +59 -0
- package/ts/src/frontDoor/render/identityRows.ts +17 -0
- package/ts/src/frontDoor/render/inspectPersona.ts +53 -0
- package/ts/src/frontDoor/render/journeyStatus.ts +78 -0
- package/ts/src/frontDoor/render/journeys.ts +79 -0
- package/ts/src/frontDoor/render/list.ts +41 -0
- package/ts/src/frontDoor/render/memories.ts +67 -0
- package/ts/src/frontDoor/render/recall.ts +49 -0
- package/ts/src/frontDoor/render/shadow.ts +155 -0
- package/ts/src/frontDoor/render/tasks.ts +99 -0
- package/ts/src/frontDoor/render/tasksImportSync.ts +63 -0
- package/ts/src/frontDoor/render/week.ts +113 -0
- package/ts/src/frontDoor/routing.ts +1001 -0
- package/ts/src/frontDoor/runtimeRoute.ts +623 -0
- package/ts/src/frontDoor/searchRoute.ts +166 -0
- package/ts/src/frontDoor/seedPaths.ts +98 -0
- package/ts/src/frontDoor/sessionStartWelcomeRoute.ts +166 -0
- package/ts/src/frontDoor/soulRoute.ts +433 -0
- package/ts/src/frontDoor/stdinSource.ts +37 -0
- package/ts/src/frontDoor/tasksImportSyncRoute.ts +110 -0
- package/ts/src/frontDoor/tasksWriteRoute.ts +101 -0
- package/ts/src/frontDoor/usage.ts +176 -0
- package/ts/src/guards/claudePlugin.ts +298 -0
- package/ts/src/guards/packContents.ts +306 -0
- package/ts/src/guards/piSourcedSkills.ts +70 -0
- package/ts/src/guards/retiredRouteShadows.ts +57 -0
- package/ts/src/guards/retiredSurfaces.ts +564 -0
- package/ts/src/hooks/claude.ts +214 -0
- package/ts/src/hooks/codex.ts +45 -0
- package/ts/src/hooks/gemini.ts +126 -0
- package/ts/src/hooks/main.ts +109 -0
- package/ts/src/hooks/mirrorState.ts +71 -0
- package/ts/src/hooks/payload.ts +73 -0
- package/ts/src/hooks/runtime.ts +179 -0
- package/ts/src/hooks/runtimeDetection.ts +34 -0
- package/ts/src/identity/applyConsolidationIdentityUpdate.ts +67 -0
- package/ts/src/identity/descriptorGenerate.ts +162 -0
- package/ts/src/identity/identityEdit.ts +143 -0
- package/ts/src/identity/identityKey.ts +77 -0
- package/ts/src/identity/identityRead.ts +69 -0
- package/ts/src/identity/identityStore.ts +80 -0
- package/ts/src/identity/journeyListing.ts +53 -0
- package/ts/src/identity/personaInspect.ts +44 -0
- package/ts/src/identity/personaListing.ts +37 -0
- package/ts/src/identity/setIdentity.ts +64 -0
- package/ts/src/index.ts +231 -0
- package/ts/src/init/init.ts +111 -0
- package/ts/src/journey/journeyOptions.ts +131 -0
- package/ts/src/journey/journeyRemoval.ts +158 -0
- package/ts/src/journey/journeyStatus.ts +149 -0
- package/ts/src/journey/journeySyncFile.ts +87 -0
- package/ts/src/journey/journeyWrite.ts +203 -0
- package/ts/src/journey/parentJourney.ts +41 -0
- package/ts/src/journey/validateParentJourney.ts +55 -0
- package/ts/src/mcp/boundary.ts +151 -0
- package/ts/src/mcp/guards.ts +244 -0
- package/ts/src/mcp/main.ts +121 -0
- package/ts/src/mcp/payload.ts +141 -0
- package/ts/src/mcp/protocol.ts +141 -0
- package/ts/src/mcp/readModels.ts +241 -0
- package/ts/src/mcp/registry.ts +201 -0
- package/ts/src/mcp/serve.ts +120 -0
- package/ts/src/mcp/tools/deterministic.ts +137 -0
- package/ts/src/mcp/tools/providerCrossing.ts +187 -0
- package/ts/src/mcp/wire.ts +8 -0
- package/ts/src/memory/journal.ts +180 -0
- package/ts/src/memory/listing.ts +107 -0
- package/ts/src/memory/memoryWrite.ts +88 -0
- package/ts/src/memory/reinforcement.ts +35 -0
- package/ts/src/mirror/context.ts +161 -0
- package/ts/src/mirror/defaultResolution.ts +199 -0
- package/ts/src/mirror/mirrorForm.ts +43 -0
- package/ts/src/mirror/orchestration.ts +364 -0
- package/ts/src/mirror/reception.ts +194 -0
- package/ts/src/mirror/render.ts +75 -0
- package/ts/src/mirror/runtimeSession.ts +205 -0
- package/ts/src/mode/operatingMode.ts +148 -0
- package/ts/src/observability/callOutcome.ts +115 -0
- package/ts/src/observability/inspectLedger.ts +329 -0
- package/ts/src/observability/ledgerHooks.ts +126 -0
- package/ts/src/observability/llmCalls.ts +154 -0
- package/ts/src/persona/detectPersona.ts +81 -0
- package/ts/src/planning/promptAssembly.ts +111 -0
- package/ts/src/planning/weekPending.ts +81 -0
- package/ts/src/planning/weekPlan.ts +183 -0
- package/ts/src/planning/weekSave.ts +117 -0
- package/ts/src/providers/config.ts +189 -0
- package/ts/src/providers/cost.ts +64 -0
- package/ts/src/providers/credits.ts +204 -0
- package/ts/src/providers/embedding.ts +321 -0
- package/ts/src/providers/familyProviders.ts +147 -0
- package/ts/src/providers/llm.ts +334 -0
- package/ts/src/providers/openrouter.ts +244 -0
- package/ts/src/providers/redaction.ts +110 -0
- package/ts/src/providers/replay.ts +15 -0
- package/ts/src/providers/transport.ts +410 -0
- package/ts/src/repair/encodingRepair.ts +253 -0
- package/ts/src/runtime/backup.ts +151 -0
- package/ts/src/runtime/channel.ts +146 -0
- package/ts/src/runtime/config.ts +168 -0
- package/ts/src/runtime/diagnose.ts +686 -0
- package/ts/src/runtime/git.ts +510 -0
- package/ts/src/runtime/installKind.ts +220 -0
- package/ts/src/runtime/migrate.ts +154 -0
- package/ts/src/runtime/packageIdentity.ts +102 -0
- package/ts/src/runtime/releaseNotes.ts +244 -0
- package/ts/src/runtime/status.ts +557 -0
- package/ts/src/runtime/strategies/clone.ts +200 -0
- package/ts/src/runtime/strategies/package.ts +328 -0
- package/ts/src/runtime/treeRoot.ts +30 -0
- package/ts/src/runtime/update.ts +445 -0
- package/ts/src/runtime/updateGate.ts +40 -0
- package/ts/src/runtime/updatePipeline.ts +159 -0
- package/ts/src/runtime/version.ts +36 -0
- package/ts/src/runtime/wiring.ts +130 -0
- package/ts/src/search/memorySearch.ts +338 -0
- package/ts/src/search/ranker.ts +154 -0
- package/ts/src/seed/seed.ts +256 -0
- package/ts/src/seed/seedYaml.ts +133 -0
- package/ts/src/soul/apply.ts +218 -0
- package/ts/src/soul/harvest.ts +267 -0
- package/ts/src/soul/prompts/soul_beauty_voice.md +103 -0
- package/ts/src/soul/prompts/soul_self_voice.md +219 -0
- package/ts/src/soul/prompts/soul_wisdom_voice.md +121 -0
- package/ts/src/soul/prompts.ts +85 -0
- package/ts/src/soul/render.ts +358 -0
- package/ts/src/soul/state.ts +212 -0
- package/ts/src/soul/transition.ts +37 -0
- package/ts/src/tasks/journeyPathParse.ts +113 -0
- package/ts/src/tasks/taskImportSync.ts +142 -0
- package/ts/src/tasks/taskStore.ts +312 -0
- package/ts/src/tasks/weekView.ts +120 -0
- package/ts/src/util/clipCodePoints.ts +26 -0
- package/ts/src/util/paths.ts +63 -0
- package/ts/src/util/program.ts +9 -0
- package/ts/src/util/pyGenerators.ts +144 -0
- package/ts/src/util/pythonText.ts +317 -0
- package/ts/src/util/semver.ts +45 -0
- package/ts/src/util/shellWord.ts +25 -0
- package/ts/src/util/slug.ts +64 -0
- package/ts/src/welcome/card.ts +339 -0
- package/ts/src/welcome/statusLine.ts +101 -0
- package/ts/src/welcome/updateCache.ts +129 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import type { WritableDatabase } from "#db/database.ts";
|
|
2
|
+
import { requireString } from "#db/rowDecode.ts";
|
|
3
|
+
import type { EmbeddingProvider } from "#providers/embedding.ts";
|
|
4
|
+
import { resolveFamilyProviders } from "#providers/familyProviders.ts";
|
|
5
|
+
import { SEARCH_TRANSPORT } from "#providers/transport.ts";
|
|
6
|
+
import type { FreshSearchResult } from "#search/memorySearch.ts";
|
|
7
|
+
import { searchMemoriesWithStatus } from "#search/memorySearch.ts";
|
|
8
|
+
import { optionValue } from "./args.ts";
|
|
9
|
+
import { ICONS } from "./render/icons.ts";
|
|
10
|
+
import { tagsText } from "./render/memories.ts";
|
|
11
|
+
|
|
12
|
+
// Mirrors Python's cli/memories.py degraded_note wording exactly (AI-04),
|
|
13
|
+
// including under a degraded search with zero results.
|
|
14
|
+
const DEGRADED_NOTE =
|
|
15
|
+
"⚠ Degraded: lexical-only search (embedding unavailable — offline or no API key).";
|
|
16
|
+
|
|
17
|
+
export interface SearchMemoryRow {
|
|
18
|
+
id: string;
|
|
19
|
+
memory_type: string;
|
|
20
|
+
layer: string;
|
|
21
|
+
title: string;
|
|
22
|
+
content: string;
|
|
23
|
+
created_at: string;
|
|
24
|
+
journey: string | null;
|
|
25
|
+
tags: string | null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Resolve the embedding provider by the same precedence the router used
|
|
30
|
+
* (CV22.DS8.US1), so the route can never disagree with the routing decision
|
|
31
|
+
* about which transport is in play.
|
|
32
|
+
*/
|
|
33
|
+
export async function resolveSearchEmbeddingProvider(
|
|
34
|
+
env: NodeJS.ProcessEnv = process.env,
|
|
35
|
+
): Promise<EmbeddingProvider> {
|
|
36
|
+
// The live provider resolves its config lazily, so a missing key surfaces
|
|
37
|
+
// inside searchMemoriesWithStatus and degrades to lexical-only rather than
|
|
38
|
+
// failing the command -- Python's behavior for an unconfigured install.
|
|
39
|
+
const family = await resolveFamilyProviders(env, SEARCH_TRANSPORT);
|
|
40
|
+
if (!family.embedding) {
|
|
41
|
+
// The search family declares an embedding fixture, so replay and live both
|
|
42
|
+
// build one; this is defense in depth, not a reachable state.
|
|
43
|
+
throw new Error("memories --search requires an embedding provider");
|
|
44
|
+
}
|
|
45
|
+
return family.embedding;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface MemorySearchRouteOptions {
|
|
49
|
+
/** Receives a content-free degraded category for the front-door log. */
|
|
50
|
+
onDegraded?: (detail: string) => void;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export async function runMemorySearchRoute(
|
|
54
|
+
db: WritableDatabase,
|
|
55
|
+
args: readonly string[],
|
|
56
|
+
options: MemorySearchRouteOptions = {},
|
|
57
|
+
): Promise<string> {
|
|
58
|
+
const query = optionValue(args, "--search");
|
|
59
|
+
if (!query) throw new Error("memories --search requires a query");
|
|
60
|
+
const provider = await resolveSearchEmbeddingProvider();
|
|
61
|
+
const limit = Number(optionValue(args, "--limit") ?? 20);
|
|
62
|
+
const { results, degraded, degradedKind } = await searchMemoriesWithStatus(db, {
|
|
63
|
+
query,
|
|
64
|
+
limit,
|
|
65
|
+
memoryType: optionValue(args, "--type"),
|
|
66
|
+
layer: optionValue(args, "--layer"),
|
|
67
|
+
journey: optionValue(args, "--journey"),
|
|
68
|
+
provider,
|
|
69
|
+
// An exploratory CLI search is not a genuine context load, so it must not
|
|
70
|
+
// reinforce: `access_count` feeds `reinforcement_score` and the hybrid
|
|
71
|
+
// ranker, and a ranker fed by its own exhaust drifts toward whatever was
|
|
72
|
+
// searched for rather than whatever was used (AI-12). Python's
|
|
73
|
+
// `cli/memories.py` has passed `log_access=False` since 2026-07-16; this
|
|
74
|
+
// port did not, and reinforced on every `memories --search` from the flip
|
|
75
|
+
// until CV22.DS9.US2 measured it. Builder context load deliberately keeps
|
|
76
|
+
// the default and still reinforces -- that one IS a genuine load.
|
|
77
|
+
logAccess: false,
|
|
78
|
+
});
|
|
79
|
+
// A degraded live search is the one failure an operator has to diagnose
|
|
80
|
+
// without a re-run, so the taxonomy class reaches the front-door log rather
|
|
81
|
+
// than dying inside the degrade path. Category only -- never a message,
|
|
82
|
+
// never the query (RS005/CR026).
|
|
83
|
+
if (degraded && degradedKind) {
|
|
84
|
+
options.onDegraded?.(`embedding_degraded kind=${degradedKind}`);
|
|
85
|
+
}
|
|
86
|
+
const rows = memoriesById(
|
|
87
|
+
db,
|
|
88
|
+
results.map((result) => result.id),
|
|
89
|
+
);
|
|
90
|
+
return formatSearchResults(query, results, rows, degraded);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Pure rendering of a fresh-search outcome (AI-04). Split out from
|
|
95
|
+
* `runMemorySearchRoute` so the degraded/normal render branches are directly
|
|
96
|
+
* unit-testable without a database or a live-failing embedding provider (none
|
|
97
|
+
* exists yet -- see CR037 plan).
|
|
98
|
+
*/
|
|
99
|
+
export function formatSearchResults(
|
|
100
|
+
query: string,
|
|
101
|
+
results: readonly FreshSearchResult[],
|
|
102
|
+
rows: ReadonlyMap<string, SearchMemoryRow>,
|
|
103
|
+
degraded: boolean,
|
|
104
|
+
): string {
|
|
105
|
+
if (results.length === 0) {
|
|
106
|
+
return degraded ? `${DEGRADED_NOTE}\n` : "No memories found.\n";
|
|
107
|
+
}
|
|
108
|
+
const lines: string[] = [];
|
|
109
|
+
if (degraded) {
|
|
110
|
+
lines.push(`${DEGRADED_NOTE} Ranked by keyword match.`, "");
|
|
111
|
+
}
|
|
112
|
+
lines.push(`🔍 Search: "${query}" (${results.length} results)`, "");
|
|
113
|
+
for (const result of results) {
|
|
114
|
+
const memory = rows.get(result.id);
|
|
115
|
+
if (!memory) continue;
|
|
116
|
+
const icon = ICONS[memory.memory_type] ?? "•";
|
|
117
|
+
const date = memory.created_at ? memory.created_at.slice(0, 10) : "?";
|
|
118
|
+
const journey = memory.journey ? ` 🧭 ${memory.journey}` : "";
|
|
119
|
+
const tags = tagsText(memory.tags);
|
|
120
|
+
lines.push(`${icon} **${memory.title}** (score: ${result.score.toFixed(3)})`);
|
|
121
|
+
lines.push(
|
|
122
|
+
` ${date} | \`${memory.id.slice(0, 8)}\` | ${memory.memory_type} [${memory.layer}]${journey}`,
|
|
123
|
+
);
|
|
124
|
+
lines.push(` ${memory.content.slice(0, 200)}`);
|
|
125
|
+
if (tags) lines.push(` 🏷 ${tags}`);
|
|
126
|
+
lines.push("");
|
|
127
|
+
}
|
|
128
|
+
return `${lines.join("\n")}\n`;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* The row reader both search faces share.
|
|
133
|
+
*
|
|
134
|
+
* Exported for `build load` (CV22.DS7.US8 plateau 7), which renders the same
|
|
135
|
+
* memories from the same ranked ids: the ranker returns `{id, score}` only, so a
|
|
136
|
+
* second copy of this query is a second chance for the two blocks to disagree
|
|
137
|
+
* about what a memory says.
|
|
138
|
+
*/
|
|
139
|
+
export function memoriesById(
|
|
140
|
+
db: WritableDatabase,
|
|
141
|
+
ids: readonly string[],
|
|
142
|
+
): Map<string, SearchMemoryRow> {
|
|
143
|
+
if (ids.length === 0) return new Map();
|
|
144
|
+
const placeholders = ids.map(() => "?").join(", ");
|
|
145
|
+
const rows = db
|
|
146
|
+
.prepare(
|
|
147
|
+
`SELECT id, memory_type, layer, title, content, created_at, journey, tags FROM memories ` +
|
|
148
|
+
`WHERE id IN (${placeholders})`,
|
|
149
|
+
)
|
|
150
|
+
.all(...ids);
|
|
151
|
+
return new Map(
|
|
152
|
+
rows.map((row) => [
|
|
153
|
+
requireString(row, "id"),
|
|
154
|
+
{
|
|
155
|
+
id: requireString(row, "id"),
|
|
156
|
+
memory_type: requireString(row, "memory_type"),
|
|
157
|
+
layer: requireString(row, "layer"),
|
|
158
|
+
title: requireString(row, "title"),
|
|
159
|
+
content: requireString(row, "content"),
|
|
160
|
+
created_at: requireString(row, "created_at"),
|
|
161
|
+
journey: typeof row.journey === "string" ? row.journey : null,
|
|
162
|
+
tags: typeof row.tags === "string" ? row.tags : null,
|
|
163
|
+
},
|
|
164
|
+
]),
|
|
165
|
+
);
|
|
166
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// `seed` path resolution — the port of the bespoke resolution inside
|
|
2
|
+
// memory.cli.seed.seed(), which is NOT the same precedence chain
|
|
3
|
+
// `resolveDbPath` (dbPath.ts) uses for every other command. Verified against
|
|
4
|
+
// the live oracle (never assumed) because it diverges in a genuinely
|
|
5
|
+
// surprising way:
|
|
6
|
+
//
|
|
7
|
+
// - `identity_root`/`mirror_home` resolve via `--mirror-home` or the plain
|
|
8
|
+
// MIRROR_HOME/MIRROR_USER chain (`resolveMirrorHome`) -- completely
|
|
9
|
+
// independent of `--env`, `MEMORY_DIR`, or `DB_PATH`.
|
|
10
|
+
// - When `--mirror-home` IS given, the database path is ALWAYS
|
|
11
|
+
// `<mirror_home>/memory.db` -- `--env` is silently ignored for the
|
|
12
|
+
// filename (`default_db_path_for_home` hardcodes "memory.db"). Confirmed
|
|
13
|
+
// live: `seed --mirror-home X --env test` writes `X/memory.db`, not
|
|
14
|
+
// `X/memory_test.db`.
|
|
15
|
+
// - When `--mirror-home` is absent and `--env` differs from the ambient
|
|
16
|
+
// `MEMORY_ENV` (or ambient is unset, defaulting "production" like Python's
|
|
17
|
+
// module-level MEMORY_ENV constant), the database path follows
|
|
18
|
+
// `db_path_for_env`: MEMORY_PROD_DIR (production only) > MEMORY_DIR > the
|
|
19
|
+
// resolved mirror home, with the env-appropriate filename -- but WITHOUT
|
|
20
|
+
// checking `DB_PATH` (that env var is only wired to the *ambient*
|
|
21
|
+
// environment in Python, cached once at import time).
|
|
22
|
+
// - When `--mirror-home` is absent and `--env` matches the ambient
|
|
23
|
+
// `MEMORY_ENV` (or is omitted), the database path follows the SAME full
|
|
24
|
+
// generic chain every other command uses (`require_db_path()` ==
|
|
25
|
+
// `resolveDbPath`).
|
|
26
|
+
//
|
|
27
|
+
// `--db-path` is a TS-front-door-only convenience (Python's `seed` CLI has no
|
|
28
|
+
// such flag), kept here for consistency with every other ported command --
|
|
29
|
+
// it wins over everything, as documented in dbPath.ts.
|
|
30
|
+
|
|
31
|
+
import { join } from "node:path";
|
|
32
|
+
import { expandHome } from "#util/paths.ts";
|
|
33
|
+
import { optionValue } from "./args.ts";
|
|
34
|
+
import {
|
|
35
|
+
type DbPathEnv,
|
|
36
|
+
type DbPathIo,
|
|
37
|
+
dbNameForEnv,
|
|
38
|
+
MirrorHomeNotConfiguredError,
|
|
39
|
+
resolveDbPath,
|
|
40
|
+
resolveMirrorHome,
|
|
41
|
+
} from "./dbPath.ts";
|
|
42
|
+
|
|
43
|
+
export interface SeedPaths {
|
|
44
|
+
dbPath: string;
|
|
45
|
+
identityRoot: string;
|
|
46
|
+
mirrorHome: string;
|
|
47
|
+
env: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Resolve `seed`'s database path, identity root, mirror home, and effective
|
|
52
|
+
* env, mirroring the Python branches documented above exactly. Throws
|
|
53
|
+
* MirrorHomeNotConfiguredError when nothing resolves (mapped to exit 2 by the
|
|
54
|
+
* caller, matching every other command's unconfigured-home contract).
|
|
55
|
+
*/
|
|
56
|
+
export function resolveSeedPaths(
|
|
57
|
+
args: readonly string[],
|
|
58
|
+
env: DbPathEnv = process.env,
|
|
59
|
+
io: DbPathIo = {},
|
|
60
|
+
): SeedPaths {
|
|
61
|
+
const explicitDbPath = optionValue(args, "--db-path");
|
|
62
|
+
const explicitMirrorHome = optionValue(args, "--mirror-home");
|
|
63
|
+
const envFlag = optionValue(args, "--env");
|
|
64
|
+
const ambientEnv = env.MEMORY_ENV || "production";
|
|
65
|
+
const effectiveEnv = envFlag || ambientEnv;
|
|
66
|
+
|
|
67
|
+
const mirrorHome = explicitMirrorHome
|
|
68
|
+
? expandHome(explicitMirrorHome)
|
|
69
|
+
: resolveMirrorHome(env, io);
|
|
70
|
+
const identityRoot = join(mirrorHome, "identity");
|
|
71
|
+
|
|
72
|
+
if (explicitDbPath) {
|
|
73
|
+
return { dbPath: expandHome(explicitDbPath), identityRoot, mirrorHome, env: effectiveEnv };
|
|
74
|
+
}
|
|
75
|
+
if (explicitMirrorHome) {
|
|
76
|
+
// default_db_path_for_home: ALWAYS "memory.db", --env is not consulted.
|
|
77
|
+
return { dbPath: join(mirrorHome, "memory.db"), identityRoot, mirrorHome, env: effectiveEnv };
|
|
78
|
+
}
|
|
79
|
+
if (envFlag && envFlag !== ambientEnv) {
|
|
80
|
+
const dbName = dbNameForEnv(envFlag);
|
|
81
|
+
let dir: string;
|
|
82
|
+
if (envFlag === "production" && env.MEMORY_PROD_DIR) {
|
|
83
|
+
dir = expandHome(env.MEMORY_PROD_DIR);
|
|
84
|
+
} else if (env.MEMORY_DIR) {
|
|
85
|
+
dir = expandHome(env.MEMORY_DIR);
|
|
86
|
+
} else {
|
|
87
|
+
dir = mirrorHome;
|
|
88
|
+
}
|
|
89
|
+
return { dbPath: join(dir, dbName), identityRoot, mirrorHome, env: effectiveEnv };
|
|
90
|
+
}
|
|
91
|
+
// require_db_path(): by construction neither --db-path nor --mirror-home is
|
|
92
|
+
// present here, so this is exactly resolveDbPath's own DB_PATH ->
|
|
93
|
+
// MEMORY_PROD_DIR -> MEMORY_DIR -> resolved-mirror-home chain -- the same
|
|
94
|
+
// one every other command uses. Reused directly rather than re-implemented.
|
|
95
|
+
return { dbPath: resolveDbPath(args, env, io), identityRoot, mirrorHome, env: effectiveEnv };
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export { MirrorHomeNotConfiguredError };
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
// `conversation-logger session-start --fast --welcome --format json` (CV9.E2.S32).
|
|
2
|
+
//
|
|
3
|
+
// The Pi extension used to open a session with three awaited front-door
|
|
4
|
+
// processes in a row -- `session-start --fast`, `welcome`, and
|
|
5
|
+
// `welcome --status-line` -- paying the loader's fixed cost three times
|
|
6
|
+
// before the user could type. They cannot run in parallel: the first WRITES
|
|
7
|
+
// the orientation the other two READ. They can run in one process, as long as
|
|
8
|
+
// the write commits before the reads. This route is that sequencing and
|
|
9
|
+
// nothing else.
|
|
10
|
+
//
|
|
11
|
+
// What it deliberately does not do:
|
|
12
|
+
//
|
|
13
|
+
// * It does not teach `loggerCli.ts` to render a welcome card. That module
|
|
14
|
+
// is the conversation domain; composition across domains is this layer's
|
|
15
|
+
// job.
|
|
16
|
+
// * It does not touch `runWelcomeRoute`'s read-only contract. Both renders
|
|
17
|
+
// run through that route with captured io, AFTER the write handle has
|
|
18
|
+
// closed, so the card and the status line are byte-identical to the
|
|
19
|
+
// standalone commands and never share the live write lock with the
|
|
20
|
+
// card's bounded update check.
|
|
21
|
+
// * It has no text form. The card is free text; the only safe delimiter is
|
|
22
|
+
// a JSON envelope.
|
|
23
|
+
//
|
|
24
|
+
// The envelope is for the extension, not for a skill. A skill that called this
|
|
25
|
+
// would put card text in front of the model through a channel the Ariad
|
|
26
|
+
// surface rules do not cover; `checkSkillCommandParity.ts` refuses the flag in
|
|
27
|
+
// every SKILL.md.
|
|
28
|
+
|
|
29
|
+
import type { WritableDatabase } from "#db/database.ts";
|
|
30
|
+
import { runConversationLoggerRoute } from "./conversationLoggerRoute.ts";
|
|
31
|
+
import { runWelcomeRoute } from "./runtimeRoute.ts";
|
|
32
|
+
|
|
33
|
+
export const SESSION_START_WELCOME_SCHEMA_VERSION = "1.0.0";
|
|
34
|
+
|
|
35
|
+
export interface SessionStartWelcomeEnvelope {
|
|
36
|
+
schemaVersion: typeof SESSION_START_WELCOME_SCHEMA_VERSION;
|
|
37
|
+
/** The logger's stdout lines, joined with `\n`: what `session-start --fast` prints. */
|
|
38
|
+
sessionStart: string;
|
|
39
|
+
/** `mirror welcome`'s stdout minus the trailing newline; `""` when disabled. */
|
|
40
|
+
welcome: string;
|
|
41
|
+
/** `mirror welcome --status-line`'s stdout minus the trailing newline; `""` when empty. */
|
|
42
|
+
statusLine: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface SessionStartWelcomeOutcome {
|
|
46
|
+
exitCode: number;
|
|
47
|
+
/** Content-free category for the front-door log when a render failed after the write. */
|
|
48
|
+
detail?: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface SessionStartWelcomeDeps {
|
|
52
|
+
/** The real write path: opens the live write database, runs `write`, closes it. */
|
|
53
|
+
withMirrorWriteDb: (
|
|
54
|
+
argv: readonly string[],
|
|
55
|
+
write: (db: WritableDatabase, dbPath: string) => Promise<number> | number,
|
|
56
|
+
) => Promise<number>;
|
|
57
|
+
/**
|
|
58
|
+
* The welcome renderer. Defaults to the real route; the render-failure test
|
|
59
|
+
* injects one that throws. The write path is never injected: it is the real
|
|
60
|
+
* one in every test.
|
|
61
|
+
*/
|
|
62
|
+
renderWelcome?: typeof runWelcomeRoute;
|
|
63
|
+
stdout?: (text: string) => void;
|
|
64
|
+
stderr?: (text: string) => void;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Only the `--fast --welcome` composite answers here; everything else is the plain logger route. */
|
|
68
|
+
export function isSessionStartWelcome(argv: readonly string[]): boolean {
|
|
69
|
+
return (
|
|
70
|
+
argv[0] === "conversation-logger" &&
|
|
71
|
+
argv.includes("session-start") &&
|
|
72
|
+
argv.includes("--welcome")
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function optionValue(args: readonly string[], name: string): string | null {
|
|
77
|
+
const index = args.indexOf(name);
|
|
78
|
+
if (index === -1) return null;
|
|
79
|
+
return args[index + 1] ?? null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** The logger's `--mirror-home` reaches the welcome renders too, so both read the same home. */
|
|
83
|
+
function welcomeArgv(argv: readonly string[], statusLine: boolean): string[] {
|
|
84
|
+
const out = ["welcome"];
|
|
85
|
+
if (statusLine) out.push("--status-line");
|
|
86
|
+
const home = optionValue(argv, "--mirror-home");
|
|
87
|
+
if (home !== null) out.push("--mirror-home", home);
|
|
88
|
+
const sessionId = optionValue(argv, "--session-id");
|
|
89
|
+
if (statusLine && sessionId !== null) out.push("--session-id", sessionId);
|
|
90
|
+
return out;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** The logger's own argv: the composite flags removed, `--format`'s value with it. */
|
|
94
|
+
function withoutCompositeFlags(argv: readonly string[]): string[] {
|
|
95
|
+
const out: string[] = [];
|
|
96
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
97
|
+
const arg = argv[i] as string;
|
|
98
|
+
if (arg === "--welcome") continue;
|
|
99
|
+
if (arg === "--format") {
|
|
100
|
+
i += 1;
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
out.push(arg);
|
|
104
|
+
}
|
|
105
|
+
return out;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function stripTrailingNewline(text: string): string {
|
|
109
|
+
return text.endsWith("\n") ? text.slice(0, -1) : text;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export async function runSessionStartWelcomeRoute(
|
|
113
|
+
argv: readonly string[],
|
|
114
|
+
deps: SessionStartWelcomeDeps,
|
|
115
|
+
): Promise<SessionStartWelcomeOutcome> {
|
|
116
|
+
const stdout = deps.stdout ?? ((text: string) => process.stdout.write(text));
|
|
117
|
+
const stderr = deps.stderr ?? ((text: string) => process.stderr.write(text));
|
|
118
|
+
const renderWelcome = deps.renderWelcome ?? runWelcomeRoute;
|
|
119
|
+
|
|
120
|
+
if (!argv.includes("--fast")) {
|
|
121
|
+
stderr("session-start: --welcome requires --fast (the full session-start runs maintenance)\n");
|
|
122
|
+
return { exitCode: 2 };
|
|
123
|
+
}
|
|
124
|
+
const format = optionValue(argv, "--format");
|
|
125
|
+
if (format !== "json") {
|
|
126
|
+
stderr(
|
|
127
|
+
"session-start: --welcome requires --format json (the card has no safe text delimiter)\n",
|
|
128
|
+
);
|
|
129
|
+
return { exitCode: 2 };
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// 1. The write, through the real path. Its handle is closed when this returns.
|
|
133
|
+
const loggerArgv = withoutCompositeFlags(argv);
|
|
134
|
+
const sessionStartLines: string[] = [];
|
|
135
|
+
const exitCode = await deps.withMirrorWriteDb(loggerArgv, (db, dbPath) =>
|
|
136
|
+
runConversationLoggerRoute(db, dbPath, loggerArgv, {
|
|
137
|
+
stdout: (line) => sessionStartLines.push(line),
|
|
138
|
+
// The logger's refusals keep going to stderr, as they do standalone.
|
|
139
|
+
stderr: (line) => stderr(`${line}\n`),
|
|
140
|
+
}),
|
|
141
|
+
);
|
|
142
|
+
if (exitCode !== 0) return { exitCode };
|
|
143
|
+
|
|
144
|
+
// 2. The reads, after the write committed and its handle closed. A render
|
|
145
|
+
// failure must not lose the unmute: the envelope still goes out, with the
|
|
146
|
+
// failed field empty, and the category reaches the front-door log.
|
|
147
|
+
let detail: string | undefined;
|
|
148
|
+
const render = (statusLine: boolean): string => {
|
|
149
|
+
let captured = "";
|
|
150
|
+
try {
|
|
151
|
+
renderWelcome(welcomeArgv(argv, statusLine), { stdout: (text) => (captured += text) });
|
|
152
|
+
} catch (error) {
|
|
153
|
+
detail = `render-failed=${error instanceof Error ? error.name : "unknown"}`;
|
|
154
|
+
return "";
|
|
155
|
+
}
|
|
156
|
+
return stripTrailingNewline(captured);
|
|
157
|
+
};
|
|
158
|
+
const envelope: SessionStartWelcomeEnvelope = {
|
|
159
|
+
schemaVersion: SESSION_START_WELCOME_SCHEMA_VERSION,
|
|
160
|
+
sessionStart: sessionStartLines.join("\n"),
|
|
161
|
+
welcome: render(false),
|
|
162
|
+
statusLine: render(true),
|
|
163
|
+
};
|
|
164
|
+
stdout(`${JSON.stringify(envelope)}\n`);
|
|
165
|
+
return detail ? { exitCode: 0, detail } : { exitCode: 0 };
|
|
166
|
+
}
|