mirror-mind 0.0.1 → 0.32.1
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-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 +561 -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 +99 -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.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 +13 -0
- package/plugins/mirror-mind/hooks/hooks.json +50 -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/mcp/launch.sh +52 -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 +65 -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/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 +576 -0
- package/ts/src/conversation/loggerCli.ts +282 -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 +1865 -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 +73 -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 +999 -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/soulRoute.ts +433 -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 +252 -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 +176 -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 +68 -0
- package/ts/src/hooks/runtime.ts +159 -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/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,513 @@
|
|
|
1
|
+
// argv -> answer for the extension-catalog READS (CV22.DS7.TS4 plateau 1).
|
|
2
|
+
//
|
|
3
|
+
// The composition layer over `catalog.ts`: the hand-rolled argument parsing
|
|
4
|
+
// `cli/extensions.py`, `cli/ext.py`, and `cli/inspect.py` do, and the exact
|
|
5
|
+
// order in which each command prints, refuses, and exits. Nothing here is
|
|
6
|
+
// routed -- `routing.ts` still sends every one of these to Python; the front
|
|
7
|
+
// door is plateau 7.
|
|
8
|
+
//
|
|
9
|
+
// The write verbs (`sync`, `install`, `uninstall`, `expose-claude`,
|
|
10
|
+
// `clean-claude`) are plateau 5 -- the plan's amendment swapped them with the
|
|
11
|
+
// dispatch, because installing a command-skill calls the extension's own
|
|
12
|
+
// `register(api)` and so DEPENDS on the host this plateau lands. Their
|
|
13
|
+
// REFUSALS live here already, because they are produced by this parser before
|
|
14
|
+
// any write is attempted, and a validated write argv raises
|
|
15
|
+
// `UnsupportedCatalogCommandError` rather than pretending: an unimplemented
|
|
16
|
+
// path must fail loudly, not silently print nothing.
|
|
17
|
+
|
|
18
|
+
import { existsSync } from "node:fs";
|
|
19
|
+
import { homedir } from "node:os";
|
|
20
|
+
import { join } from "node:path";
|
|
21
|
+
import type { WritableDatabase } from "#db/database.ts";
|
|
22
|
+
import { PROGRAM } from "#util/program.ts";
|
|
23
|
+
import {
|
|
24
|
+
type BindingDeps,
|
|
25
|
+
parseBindingTail,
|
|
26
|
+
runBind,
|
|
27
|
+
runBindings,
|
|
28
|
+
runMigrate,
|
|
29
|
+
runUnbind,
|
|
30
|
+
} from "./bindings.ts";
|
|
31
|
+
import {
|
|
32
|
+
discoverExtensions,
|
|
33
|
+
extensionsRootForHome,
|
|
34
|
+
filterManifestsForRuntime,
|
|
35
|
+
type RenderedCommand,
|
|
36
|
+
renderCommandSkillList,
|
|
37
|
+
renderExtensionList,
|
|
38
|
+
renderInspectExtension,
|
|
39
|
+
renderInspectRuntimeCatalog,
|
|
40
|
+
runtimeSkillsRootForHome,
|
|
41
|
+
} from "./catalog.ts";
|
|
42
|
+
import {
|
|
43
|
+
cleanupClaudeRuntimeSkills,
|
|
44
|
+
exposeClaudeRuntimeSkills,
|
|
45
|
+
installExtension,
|
|
46
|
+
loadRuntimeCatalog,
|
|
47
|
+
renderInstallReport,
|
|
48
|
+
renderUninstallReport,
|
|
49
|
+
syncExtensionsForRuntime,
|
|
50
|
+
uninstallExtension,
|
|
51
|
+
} from "./catalogWrites.ts";
|
|
52
|
+
import {
|
|
53
|
+
type ExtensionDispatch,
|
|
54
|
+
extensionNotInstalled,
|
|
55
|
+
installedExtensionDir,
|
|
56
|
+
noRuntimeRefusal,
|
|
57
|
+
readDeclaredCommands,
|
|
58
|
+
readSubcommandListing,
|
|
59
|
+
renderSubcommandListing,
|
|
60
|
+
} from "./dispatch.ts";
|
|
61
|
+
import { ExtensionValidationError } from "./errors.ts";
|
|
62
|
+
|
|
63
|
+
export class UnsupportedCatalogCommandError extends Error {}
|
|
64
|
+
|
|
65
|
+
const EXTENSIONS_USAGE =
|
|
66
|
+
`Usage: ${PROGRAM} extensions [list|validate|sync|install|uninstall|` +
|
|
67
|
+
"expose-claude|clean-claude] [--mirror-home PATH] [--extensions-root PATH] " +
|
|
68
|
+
"[--runtime NAME] [--target-root PATH]";
|
|
69
|
+
const LIST_USAGE =
|
|
70
|
+
`Usage: ${PROGRAM} list [personas|journeys|extensions|all] ` +
|
|
71
|
+
"[--mirror-home PATH] [--verbose] [--extensions-root PATH] [--runtime NAME]";
|
|
72
|
+
const INSPECT_USAGE =
|
|
73
|
+
`Usage: ${PROGRAM} inspect persona|extension|runtime-catalog|llm-calls|` +
|
|
74
|
+
"embedding-provenance <id> [--mirror-home PATH] [--extensions-root PATH]";
|
|
75
|
+
const EXT_USAGE = [
|
|
76
|
+
"Usage:",
|
|
77
|
+
` ${PROGRAM} ext list`,
|
|
78
|
+
` ${PROGRAM} ext <id> [--help]`,
|
|
79
|
+
` ${PROGRAM} ext <id> <subcommand> [args...]`,
|
|
80
|
+
` ${PROGRAM} ext <id> bind <capability> (--persona <id> | --journey <id> | --global)`,
|
|
81
|
+
` ${PROGRAM} ext <id> unbind <capability> (--persona <id> | --journey <id> | --global)`,
|
|
82
|
+
` ${PROGRAM} ext <id> bindings`,
|
|
83
|
+
` ${PROGRAM} ext <id> migrate`,
|
|
84
|
+
"",
|
|
85
|
+
].join("\n");
|
|
86
|
+
|
|
87
|
+
const EXTENSIONS_VERBS = new Set([
|
|
88
|
+
"list",
|
|
89
|
+
"validate",
|
|
90
|
+
"sync",
|
|
91
|
+
"install",
|
|
92
|
+
"uninstall",
|
|
93
|
+
"expose-claude",
|
|
94
|
+
"clean-claude",
|
|
95
|
+
]);
|
|
96
|
+
|
|
97
|
+
/** Everything these commands need from the environment, passed, never read. */
|
|
98
|
+
export interface CatalogContext {
|
|
99
|
+
/** The resolved Mirror home; `--mirror-home` has already been applied. */
|
|
100
|
+
readonly mirrorHome: string;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** The writable half, for the four `ext` verbs that touch the database. */
|
|
104
|
+
export interface ExtWriteContext extends CatalogContext {
|
|
105
|
+
readonly db: WritableDatabase;
|
|
106
|
+
readonly deps: BindingDeps;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const BUILTIN_VERBS = new Set(["bind", "unbind", "bindings", "migrate"]);
|
|
110
|
+
const HELP_FLAGS = new Set(["--help", "-h", "help"]);
|
|
111
|
+
|
|
112
|
+
const BUILTIN_VERB_HELP: Record<string, readonly [string, string]> = {
|
|
113
|
+
bind: [
|
|
114
|
+
"bind <capability> (--persona <id> | --journey <id> | --global)",
|
|
115
|
+
"Bind a capability to a persona, a journey, or every context.",
|
|
116
|
+
],
|
|
117
|
+
unbind: [
|
|
118
|
+
"unbind <capability> (--persona <id> | --journey <id> | --global)",
|
|
119
|
+
"Remove a capability binding.",
|
|
120
|
+
],
|
|
121
|
+
bindings: ["bindings", "List the extension's capability bindings."],
|
|
122
|
+
migrate: ["migrate", "Apply the extension's pending database migrations."],
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
function out(stdout: string, exitCode = 0): RenderedCommand {
|
|
126
|
+
return { stdout, stderr: "", exitCode };
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function usage(text: string): RenderedCommand {
|
|
130
|
+
return out(`${text}\n`, 1);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
interface ParsedOptions {
|
|
134
|
+
extensionsRoot: string | null;
|
|
135
|
+
mirrorHome: string | null;
|
|
136
|
+
runtime: string | null;
|
|
137
|
+
targetRoot: string | null;
|
|
138
|
+
positional: string[];
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Port of `extensions._parse_args`.
|
|
143
|
+
*
|
|
144
|
+
* A flag whose value is missing is NOT an error here: the loop's `i + 1 <
|
|
145
|
+
* len(args)` guard fails, so a trailing `--runtime` falls through to the
|
|
146
|
+
* positional list and is read as a subcommand. Reproduced deliberately.
|
|
147
|
+
*/
|
|
148
|
+
export function parseCatalogOptions(argv: readonly string[]): ParsedOptions {
|
|
149
|
+
const parsed: ParsedOptions = {
|
|
150
|
+
extensionsRoot: null,
|
|
151
|
+
mirrorHome: null,
|
|
152
|
+
runtime: null,
|
|
153
|
+
targetRoot: null,
|
|
154
|
+
positional: [],
|
|
155
|
+
};
|
|
156
|
+
let index = 0;
|
|
157
|
+
while (index < argv.length) {
|
|
158
|
+
const token = argv[index] as string;
|
|
159
|
+
const value = argv[index + 1];
|
|
160
|
+
if (token === "--extensions-root" && value !== undefined) {
|
|
161
|
+
parsed.extensionsRoot = value;
|
|
162
|
+
index += 2;
|
|
163
|
+
} else if (token === "--mirror-home" && value !== undefined) {
|
|
164
|
+
parsed.mirrorHome = value;
|
|
165
|
+
index += 2;
|
|
166
|
+
} else if (token === "--runtime" && value !== undefined) {
|
|
167
|
+
parsed.runtime = value;
|
|
168
|
+
index += 2;
|
|
169
|
+
} else if (token === "--target-root" && value !== undefined) {
|
|
170
|
+
parsed.targetRoot = value;
|
|
171
|
+
index += 2;
|
|
172
|
+
} else {
|
|
173
|
+
parsed.positional.push(token);
|
|
174
|
+
index += 1;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return parsed;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function resolveRoot(context: CatalogContext, explicit: string | null): string {
|
|
181
|
+
return explicit ?? extensionsRootForHome(context.mirrorHome);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/** Python's `Path(p).expanduser()`, which the two `--target-root` verbs apply. */
|
|
185
|
+
function expandHomePath(path: string): string {
|
|
186
|
+
if (path === "~") return homedir();
|
|
187
|
+
if (path.startsWith("~/")) return join(homedir(), path.slice(2));
|
|
188
|
+
return path;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function writeContext(context: CatalogContext, command: string): ExtWriteContext {
|
|
192
|
+
if (!isWriteContext(context)) {
|
|
193
|
+
throw new UnsupportedCatalogCommandError(`extensions ${command} needs a write context`);
|
|
194
|
+
}
|
|
195
|
+
return context;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Python lets `install`'s validation errors escape as a traceback: exit 1,
|
|
200
|
+
* nothing on stdout. TypeScript cannot reproduce those bytes, so it answers
|
|
201
|
+
* the recorded divergence shape -- the same exit code, one line on stderr --
|
|
202
|
+
* and, like Python, writes nothing to stdout.
|
|
203
|
+
*/
|
|
204
|
+
function failLoudly(run: () => RenderedCommand): RenderedCommand {
|
|
205
|
+
try {
|
|
206
|
+
return run();
|
|
207
|
+
} catch (error) {
|
|
208
|
+
if (!(error instanceof ExtensionValidationError)) throw error;
|
|
209
|
+
return { stdout: "", stderr: `${error.message}\n`, exitCode: 1 };
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/** Port of the read half of `cmd_extensions`. */
|
|
214
|
+
export function runExtensionsCommand(
|
|
215
|
+
context: CatalogContext,
|
|
216
|
+
argv: readonly string[],
|
|
217
|
+
): RenderedCommand {
|
|
218
|
+
const options = parseCatalogOptions(argv);
|
|
219
|
+
const command = options.positional[0] ?? "list";
|
|
220
|
+
if (!EXTENSIONS_VERBS.has(command)) return usage(EXTENSIONS_USAGE);
|
|
221
|
+
|
|
222
|
+
if (command === "install") {
|
|
223
|
+
if (options.positional.length !== 2) {
|
|
224
|
+
return usage(
|
|
225
|
+
`Usage: ${PROGRAM} extensions install <id> [--extensions-root PATH] ` +
|
|
226
|
+
"[--mirror-home PATH] [--runtime NAME]",
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
if (options.extensionsRoot === null) return usage("install requires --extensions-root PATH");
|
|
230
|
+
const write = writeContext(context, "install");
|
|
231
|
+
return failLoudly(() =>
|
|
232
|
+
renderInstallReport(
|
|
233
|
+
installExtension({
|
|
234
|
+
extensionId: options.positional[1] as string,
|
|
235
|
+
sourceRoot: options.extensionsRoot as string,
|
|
236
|
+
mirrorHome: write.mirrorHome,
|
|
237
|
+
runtime: options.runtime,
|
|
238
|
+
db: write.db,
|
|
239
|
+
deps: write.deps,
|
|
240
|
+
}),
|
|
241
|
+
),
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
if (command === "uninstall") {
|
|
245
|
+
if (options.positional.length !== 2) {
|
|
246
|
+
return usage(
|
|
247
|
+
`Usage: ${PROGRAM} extensions uninstall <id> [--mirror-home PATH] [--runtime NAME]`,
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
const write = writeContext(context, "uninstall");
|
|
251
|
+
// Python CATCHES the validation error here and prints it as a line, where
|
|
252
|
+
// `install` lets the same class escape as a traceback. Same command, two
|
|
253
|
+
// refusal shapes, measured rather than unified.
|
|
254
|
+
try {
|
|
255
|
+
return renderUninstallReport(
|
|
256
|
+
uninstallExtension({
|
|
257
|
+
extensionId: options.positional[1] as string,
|
|
258
|
+
mirrorHome: write.mirrorHome,
|
|
259
|
+
runtime: options.runtime,
|
|
260
|
+
db: write.db,
|
|
261
|
+
deps: write.deps,
|
|
262
|
+
}),
|
|
263
|
+
);
|
|
264
|
+
} catch (error) {
|
|
265
|
+
if (!(error instanceof ExtensionValidationError)) throw error;
|
|
266
|
+
return out(`${error.message}\n`, 1);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
if (command === "expose-claude" || command === "clean-claude") {
|
|
270
|
+
if (options.targetRoot === null) return usage(`${command} requires --target-root PATH`);
|
|
271
|
+
const write = writeContext(context, command);
|
|
272
|
+
const projectRoot = expandHomePath(options.targetRoot);
|
|
273
|
+
if (command === "clean-claude") {
|
|
274
|
+
const report = cleanupClaudeRuntimeSkills(projectRoot);
|
|
275
|
+
const lines = [
|
|
276
|
+
`Removed Claude external skills from ${report.claudeSkillsRoot}`,
|
|
277
|
+
` overlay catalog: ${report.overlayCatalogPath}`,
|
|
278
|
+
...report.removed.map((path) => ` removed ${path}`),
|
|
279
|
+
];
|
|
280
|
+
return out(`${lines.join("\n")}\n`);
|
|
281
|
+
}
|
|
282
|
+
try {
|
|
283
|
+
const catalog = loadRuntimeCatalog("claude", write.mirrorHome);
|
|
284
|
+
const report = exposeClaudeRuntimeSkills(projectRoot, catalog);
|
|
285
|
+
const lines = [
|
|
286
|
+
`Exposed Claude external skills into ${report.claudeSkillsRoot}`,
|
|
287
|
+
` overlay catalog: ${report.overlayCatalogPath}`,
|
|
288
|
+
...report.removed.map((path) => ` pruned ${path}`),
|
|
289
|
+
...report.exposed.map((item) => ` ${item.commandName} -> ${item.targetSkillPath}`),
|
|
290
|
+
];
|
|
291
|
+
return out(`${lines.join("\n")}\n`);
|
|
292
|
+
} catch (error) {
|
|
293
|
+
if (!(error instanceof ExtensionValidationError)) throw error;
|
|
294
|
+
return out(`${error.message}\n`, 1);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
const root = resolveRoot(context, options.extensionsRoot);
|
|
299
|
+
const discovery = discoverExtensions(root);
|
|
300
|
+
const manifests = filterManifestsForRuntime(discovery.manifests, options.runtime);
|
|
301
|
+
|
|
302
|
+
if (command === "list") {
|
|
303
|
+
const header = options.runtime === null ? "" : `Runtime filter: ${options.runtime}\n`;
|
|
304
|
+
return out(header + renderExtensionList(manifests, discovery.errors, root));
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// `validate` and `sync` share this prelude, and its ORDER is the measured
|
|
308
|
+
// surprise: an invalid extension exits 1 here, BEFORE `sync` can complain
|
|
309
|
+
// about a missing `--runtime`. This INVALID block also has no leading blank
|
|
310
|
+
// line, unlike the one inside `print_extension_list`.
|
|
311
|
+
let stdout = `Extensions root: ${root}\n`;
|
|
312
|
+
if (options.runtime !== null) stdout += `Runtime filter: ${options.runtime}\n`;
|
|
313
|
+
if (discovery.errors.length > 0) {
|
|
314
|
+
stdout += "=== INVALID EXTENSIONS ===\n";
|
|
315
|
+
for (const [extensionId, message] of discovery.errors) {
|
|
316
|
+
stdout += ` ${extensionId}: ${message}\n`;
|
|
317
|
+
}
|
|
318
|
+
return out(stdout, 1);
|
|
319
|
+
}
|
|
320
|
+
if (command === "validate") {
|
|
321
|
+
return out(`${stdout}Validated ${manifests.length} extension(s).\n`);
|
|
322
|
+
}
|
|
323
|
+
if (options.runtime === null) return out(`${stdout}sync requires --runtime\n`, 1);
|
|
324
|
+
if (options.targetRoot === null) return out(`${stdout}sync requires --target-root PATH\n`, 1);
|
|
325
|
+
|
|
326
|
+
// `sync` writes files but never the database, so it needs the clock seam and
|
|
327
|
+
// nothing else. Note the target root is used RAW, not expanded: only
|
|
328
|
+
// `expose-claude` and `clean-claude` call `expanduser` on theirs.
|
|
329
|
+
const write = writeContext(context, "sync");
|
|
330
|
+
const synced = syncExtensionsForRuntime(
|
|
331
|
+
manifests,
|
|
332
|
+
options.runtime,
|
|
333
|
+
options.targetRoot,
|
|
334
|
+
write.deps,
|
|
335
|
+
);
|
|
336
|
+
const lines = [
|
|
337
|
+
`${stdout}Synced ${synced.length} extension(s) to ${options.targetRoot}`,
|
|
338
|
+
...synced.map((item) => ` ${item.command_name} -> ${item.installed_skill_path}`),
|
|
339
|
+
];
|
|
340
|
+
return out(`${lines.join("\n")}\n`);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Port of `cmd_ext`: the top-level parse, `_cmd_list`, `_print_top_help`, the
|
|
345
|
+
* built-in verbs, and the DECISION to dispatch into an extension.
|
|
346
|
+
*
|
|
347
|
+
* It answers with bytes for everything it can decide alone, and with an
|
|
348
|
+
* `ExtensionDispatch` for `ext <id>` and `ext <id> <subcommand>` -- the two
|
|
349
|
+
* leaves that must load extension code. Deciding and executing are separate on
|
|
350
|
+
* purpose: this layer stays pure and testable, and only the caller that is
|
|
351
|
+
* allowed to spawn a process runs the decision.
|
|
352
|
+
*/
|
|
353
|
+
export function runExtCommand(
|
|
354
|
+
context: CatalogContext,
|
|
355
|
+
argv: readonly string[],
|
|
356
|
+
): RenderedCommand | ExtensionDispatch {
|
|
357
|
+
const args: string[] = [];
|
|
358
|
+
let mirrorHome: string | null = null;
|
|
359
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
360
|
+
const token = argv[index] as string;
|
|
361
|
+
const value = argv[index + 1];
|
|
362
|
+
if (token === "--mirror-home" && value !== undefined) {
|
|
363
|
+
mirrorHome = value;
|
|
364
|
+
index += 1;
|
|
365
|
+
continue;
|
|
366
|
+
}
|
|
367
|
+
args.push(token);
|
|
368
|
+
}
|
|
369
|
+
const home = mirrorHome ?? context.mirrorHome;
|
|
370
|
+
const head = args[0];
|
|
371
|
+
// A bare `ext` and `ext --help` print the SAME bytes and differ only in the
|
|
372
|
+
// exit code. Measured, not assumed.
|
|
373
|
+
if (head === undefined) return out(EXT_USAGE, 1);
|
|
374
|
+
if (head === "--help" || head === "-h" || head === "help") return out(EXT_USAGE, 0);
|
|
375
|
+
if (head === "list") {
|
|
376
|
+
const root = extensionsRootForHome(home);
|
|
377
|
+
const discovery = discoverExtensions(root);
|
|
378
|
+
return out(renderCommandSkillList(discovery.manifests, discovery.errors, root));
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
const extensionId = head;
|
|
382
|
+
const rest = args.slice(1);
|
|
383
|
+
const verb = rest[0];
|
|
384
|
+
// `ext <id>` lists the extension's subcommands, and Python models that as a
|
|
385
|
+
// dispatch of `--help` rather than as a command of its own.
|
|
386
|
+
if (verb === undefined) return dispatchOrNotInstalled(home, extensionId, "--help", []);
|
|
387
|
+
const tail = rest.slice(1);
|
|
388
|
+
|
|
389
|
+
// Describe, never execute: this guard is a fix `cli/ext.py` carries, and
|
|
390
|
+
// losing it would make `ext <id> migrate --help` APPLY migrations.
|
|
391
|
+
if (BUILTIN_VERBS.has(verb) && tail.some((token) => HELP_FLAGS.has(token))) {
|
|
392
|
+
const [usage, description] = BUILTIN_VERB_HELP[verb] as readonly [string, string];
|
|
393
|
+
return out(`Usage:\n ${PROGRAM} ext ${extensionId} ${usage}\n\n${description}\n`);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
if (!BUILTIN_VERBS.has(verb)) return dispatchOrNotInstalled(home, extensionId, verb, tail);
|
|
397
|
+
if (!isWriteContext(context)) {
|
|
398
|
+
throw new UnsupportedCatalogCommandError(`ext ${verb} needs a writable database`);
|
|
399
|
+
}
|
|
400
|
+
if (verb === "bindings") return runBindings(context.db, extensionId);
|
|
401
|
+
if (verb === "migrate") return runMigrate(context.db, home, extensionId, context.deps);
|
|
402
|
+
|
|
403
|
+
const parsed = parseBindingTail(extensionId, verb === "bind" ? "bind" : "unbind", tail);
|
|
404
|
+
if ("stdout" in parsed) return parsed;
|
|
405
|
+
const target = { kind: parsed.kind, id: parsed.id };
|
|
406
|
+
return verb === "bind"
|
|
407
|
+
? runBind(context.db, extensionId, parsed.capabilityId, target, context.deps)
|
|
408
|
+
: runUnbind(context.db, extensionId, parsed.capabilityId, target);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
function isWriteContext(context: CatalogContext): context is ExtWriteContext {
|
|
412
|
+
return "db" in context;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Decide what `ext <id> [subcommand]` does, without running anything.
|
|
417
|
+
*
|
|
418
|
+
* The installed check `_dispatch_subcommand` ran before loading anything, and
|
|
419
|
+
* its refusal prints the path Python BUILT, not the path it would resolve --
|
|
420
|
+
* see `installedExtensionDir` for why that distinction is observable.
|
|
421
|
+
*
|
|
422
|
+
* After CV22.DS10.TS2 there are five outcomes and only the last one is a
|
|
423
|
+
* process:
|
|
424
|
+
*
|
|
425
|
+
* 1. not installed -> Python's byte-identical refusal
|
|
426
|
+
* 2. a help spelling -> the manifest-rendered listing
|
|
427
|
+
* 3. a name the manifest does not document -> unknown + the listing
|
|
428
|
+
* 4. documented, no runtime -> the refusal, on stderr, exit 1
|
|
429
|
+
* 5. documented with a runtime -> an `ExtensionDispatch` for the caller
|
|
430
|
+
* that is allowed to spawn
|
|
431
|
+
*
|
|
432
|
+
* Cases 3 and 4 are deliberately distinct. "I have never heard of that" and
|
|
433
|
+
* "that exists but has not been migrated" are different problems with
|
|
434
|
+
* different fixes, and collapsing them would send a user editing the wrong
|
|
435
|
+
* file.
|
|
436
|
+
*/
|
|
437
|
+
function dispatchOrNotInstalled(
|
|
438
|
+
mirrorHome: string,
|
|
439
|
+
extensionId: string,
|
|
440
|
+
subcommand: string,
|
|
441
|
+
argv: readonly string[],
|
|
442
|
+
): RenderedCommand | ExtensionDispatch {
|
|
443
|
+
const extensionRoot = installedExtensionDir(mirrorHome, extensionId);
|
|
444
|
+
if (!existsSync(extensionRoot)) return extensionNotInstalled(mirrorHome, extensionId);
|
|
445
|
+
|
|
446
|
+
const entries = readSubcommandListing(extensionRoot);
|
|
447
|
+
if (HELP_FLAGS.has(subcommand)) return out(renderSubcommandListing(extensionId, entries));
|
|
448
|
+
|
|
449
|
+
const documented = entries.find((entry) => entry.name === subcommand);
|
|
450
|
+
if (documented === undefined) {
|
|
451
|
+
return out(
|
|
452
|
+
`unknown subcommand '${subcommand}' for extension/${extensionId}\n` +
|
|
453
|
+
renderSubcommandListing(extensionId, entries),
|
|
454
|
+
1,
|
|
455
|
+
);
|
|
456
|
+
}
|
|
457
|
+
const declared = readDeclaredCommands(extensionRoot).find((entry) => entry.name === subcommand);
|
|
458
|
+
if (declared === undefined) {
|
|
459
|
+
return { stdout: "", stderr: noRuntimeRefusal(extensionId, subcommand), exitCode: 1 };
|
|
460
|
+
}
|
|
461
|
+
return {
|
|
462
|
+
kind: "extension-subcommand",
|
|
463
|
+
extensionId,
|
|
464
|
+
subcommand,
|
|
465
|
+
argv: [...argv],
|
|
466
|
+
mirrorHome,
|
|
467
|
+
extensionRoot,
|
|
468
|
+
command: declared.command,
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
/** Port of `cmd_list`'s extension branch and its usage refusal. */
|
|
473
|
+
export function runListCommand(context: CatalogContext, argv: readonly string[]): RenderedCommand {
|
|
474
|
+
const options = parseCatalogOptions(argv);
|
|
475
|
+
const target = options.positional[0] ?? "all";
|
|
476
|
+
if (!["personas", "journeys", "extensions", "all"].includes(target)) return usage(LIST_USAGE);
|
|
477
|
+
if (target !== "extensions") {
|
|
478
|
+
// `personas`, `journeys`, and the persona/journey halves of `all` are
|
|
479
|
+
// DS7.US1's ported reads; the front-door composition is plateau 7.
|
|
480
|
+
throw new UnsupportedCatalogCommandError(`list ${target} composes the DS7.US1 reads`);
|
|
481
|
+
}
|
|
482
|
+
const root = resolveRoot(context, options.extensionsRoot);
|
|
483
|
+
const discovery = discoverExtensions(root);
|
|
484
|
+
const manifests = filterManifestsForRuntime(discovery.manifests, options.runtime);
|
|
485
|
+
const header = options.runtime === null ? "" : `Runtime filter: ${options.runtime}\n`;
|
|
486
|
+
return out(header + renderExtensionList(manifests, discovery.errors, root));
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/** Port of `cmd_inspect`'s catalog targets and its usage refusal. */
|
|
490
|
+
export function runInspectCommand(
|
|
491
|
+
context: CatalogContext,
|
|
492
|
+
argv: readonly string[],
|
|
493
|
+
): RenderedCommand {
|
|
494
|
+
const options = parseCatalogOptions(argv);
|
|
495
|
+
const [target, targetId] = options.positional;
|
|
496
|
+
if (
|
|
497
|
+
options.positional.length !== 2 ||
|
|
498
|
+
target === undefined ||
|
|
499
|
+
!["persona", "extension", "runtime-catalog"].includes(target)
|
|
500
|
+
) {
|
|
501
|
+
return usage(INSPECT_USAGE);
|
|
502
|
+
}
|
|
503
|
+
if (target === "persona") {
|
|
504
|
+
throw new UnsupportedCatalogCommandError("inspect persona is DS7.US1's ported read");
|
|
505
|
+
}
|
|
506
|
+
if (target === "extension") {
|
|
507
|
+
return renderInspectExtension(resolveRoot(context, options.extensionsRoot), targetId as string);
|
|
508
|
+
}
|
|
509
|
+
const runtime = targetId as string;
|
|
510
|
+
return out(
|
|
511
|
+
renderInspectRuntimeCatalog(runtimeSkillsRootForHome(context.mirrorHome, runtime), runtime),
|
|
512
|
+
);
|
|
513
|
+
}
|