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,227 @@
|
|
|
1
|
+
// CR112 — reading a story-package artifact back and saying what it is.
|
|
2
|
+
//
|
|
3
|
+
// Plan and Expand write scaffolds where no file exists and never touch a file that
|
|
4
|
+
// does (CR079). Until CR112 that was the whole story: `build show` said present or
|
|
5
|
+
// missing, and no approval read a file, so a scaffold nobody had authored was
|
|
6
|
+
// approvable on both story routes. This module answers the question the surfaces
|
|
7
|
+
// and the approvals need: is this file still the scaffold, and which of its sections
|
|
8
|
+
// are still waiting to be written?
|
|
9
|
+
//
|
|
10
|
+
// The verdict is structural, never a judgement of prose. A section is
|
|
11
|
+
//
|
|
12
|
+
// * `missing` -- the file, or the `## ` heading, is not there;
|
|
13
|
+
// * `unfilled` -- empty, or holding a line that starts with `pending`, is a
|
|
14
|
+
// throwaway token, or matches the placeholder pattern: the rule
|
|
15
|
+
// Python's `unfilled_plan_sections_for` applied;
|
|
16
|
+
// * `scaffold` -- every non-blank line is one the scaffold would write under this
|
|
17
|
+
// heading, with the `{title}` slot wildcarded;
|
|
18
|
+
// * `authored` -- anything else. One real line under a heading is authored.
|
|
19
|
+
//
|
|
20
|
+
// `unfilled` is judged before `scaffold`, so a section that holds a `TODO` beside the
|
|
21
|
+
// template is unfilled, not scaffold, and either way not authored.
|
|
22
|
+
//
|
|
23
|
+
// Only `placeholder` sections decide the file's word. A `default` section is a rule
|
|
24
|
+
// the Driver may keep verbatim. For `plan.md` every placeholder heading is required and
|
|
25
|
+
// a missing one counts against the file, as the Plan contract has always required; for
|
|
26
|
+
// `index.md` and `test-guide.md` a missing heading is the Driver's structure, not a
|
|
27
|
+
// scaffold, and only sections that are present and still the scaffold's count.
|
|
28
|
+
//
|
|
29
|
+
// The file's word follows its judged sections: `authored` when nothing is left to
|
|
30
|
+
// write, `partly authored` when some are authored, `scaffold` when none is and the file
|
|
31
|
+
// still carries the scaffold's text, and `incomplete` when none is and none of it is
|
|
32
|
+
// the scaffold's -- a file a person wrote without the sections the contract requires.
|
|
33
|
+
// Calling that file a scaffold would say Ariad wrote what it did not.
|
|
34
|
+
//
|
|
35
|
+
// CR111 D4: for `plan.md` the LIST of sections still to write is what approval would
|
|
36
|
+
// refuse: `PLAN_APPROVAL_SECTIONS`, which adds the two required `default` sections,
|
|
37
|
+
// Non-Goals and the Implementation Contract, while they are missing or empty. Until
|
|
38
|
+
// then `build show` could say `authored` over an approval that refused. The two
|
|
39
|
+
// required defaults lengthen the list; they never decide the word, or an untouched
|
|
40
|
+
// scaffold, whose defaults are filled, would read `partly authored`. Approval reads
|
|
41
|
+
// the same list (`planSectionsToAuthor`), so no surface can disagree with it.
|
|
42
|
+
|
|
43
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
44
|
+
import { pySplitLines, pyStrip } from "#util/pythonText.ts";
|
|
45
|
+
import {
|
|
46
|
+
matchesTemplate,
|
|
47
|
+
PLAN_APPROVAL_SECTIONS,
|
|
48
|
+
PLAN_SECTIONS,
|
|
49
|
+
type SectionSpec,
|
|
50
|
+
STORY_INDEX_SECTIONS,
|
|
51
|
+
TEST_GUIDE_SECTIONS,
|
|
52
|
+
} from "./scaffoldSections.ts";
|
|
53
|
+
|
|
54
|
+
export type SectionState = "missing" | "unfilled" | "scaffold" | "authored";
|
|
55
|
+
export type ArtifactState = "missing" | "scaffold" | "incomplete" | "partly_authored" | "authored";
|
|
56
|
+
export type ArtifactName = "index.md" | "plan.md" | "test-guide.md";
|
|
57
|
+
|
|
58
|
+
/** The state word a surface prints beside an artifact's name. */
|
|
59
|
+
export function describeArtifactState(state: ArtifactState): string {
|
|
60
|
+
return state === "partly_authored" ? "partly authored" : state;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface SectionVerdict {
|
|
64
|
+
readonly header: string;
|
|
65
|
+
readonly state: SectionState;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface ArtifactVerdict {
|
|
69
|
+
readonly name: ArtifactName;
|
|
70
|
+
readonly state: ArtifactState;
|
|
71
|
+
/** Every placeholder section the reader judged, in the artifact's own order. */
|
|
72
|
+
readonly sections: readonly SectionVerdict[];
|
|
73
|
+
/**
|
|
74
|
+
* The sections still to be written, by their exact `## ` text, in the file's order:
|
|
75
|
+
* the placeholder sections not authored and, for `plan.md`, the required default
|
|
76
|
+
* sections missing or empty -- exactly what a Plan approval would refuse on.
|
|
77
|
+
*/
|
|
78
|
+
readonly toAuthor: readonly string[];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Python `_PLACEHOLDER_LINE_RE`.
|
|
83
|
+
*
|
|
84
|
+
* `^(?:[-*]\s+)?(?:this (?:section )?is (?:a )?)?placeholder(?:\b|$)`, case
|
|
85
|
+
* insensitive. `\s` is Python's, which matches more than JavaScript's — but this
|
|
86
|
+
* pattern's `\s+` sits between an ASCII bullet and the word, where the two agree.
|
|
87
|
+
* The `\b` alternative is what keeps "placeholder story" a placeholder while
|
|
88
|
+
* "placeholders" is not; and the whole point is that it anchors at the START, so
|
|
89
|
+
* "Do not implement the sibling Payment placeholder story" is product vocabulary,
|
|
90
|
+
* not an unfilled section.
|
|
91
|
+
*/
|
|
92
|
+
export const PLACEHOLDER_LINE_RE =
|
|
93
|
+
/^(?:[-*]\s+)?(?:this (?:section )?is (?:a )?)?placeholder(?:\b|$)/i;
|
|
94
|
+
|
|
95
|
+
const THROWAWAY = new Set(["todo", "tbd", "...", "n/a", "none"]);
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Python `_level_two_sections`.
|
|
99
|
+
*
|
|
100
|
+
* `setdefault` means a REPEATED `## Scope` heading appends to the first section
|
|
101
|
+
* rather than replacing it, so a Plan with two Scope headings is complete if either
|
|
102
|
+
* carries content.
|
|
103
|
+
*/
|
|
104
|
+
export function levelTwoSections(text: string): Map<string, string> {
|
|
105
|
+
const sections = new Map<string, string[]>();
|
|
106
|
+
let current: string | null = null;
|
|
107
|
+
for (const line of pySplitLines(text)) {
|
|
108
|
+
if (line.startsWith("## ")) {
|
|
109
|
+
current = pyStrip(line.slice(3));
|
|
110
|
+
if (!sections.has(current)) sections.set(current, []);
|
|
111
|
+
} else if (current !== null) {
|
|
112
|
+
sections.get(current)?.push(line);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
const joined = new Map<string, string>();
|
|
116
|
+
for (const [header, lines] of sections) joined.set(header, lines.join("\n"));
|
|
117
|
+
return joined;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** The unfilled rule, Python's `unfilled_plan_sections_for`, for one section's body. */
|
|
121
|
+
export function isUnfilledBody(body: string): boolean {
|
|
122
|
+
const stripped = pyStrip(body);
|
|
123
|
+
if (!stripped) return true;
|
|
124
|
+
const lines = pySplitLines(stripped)
|
|
125
|
+
.map((line) => pyStrip(line).toLowerCase())
|
|
126
|
+
.filter((line) => line !== "");
|
|
127
|
+
return (
|
|
128
|
+
lines.some((line) => line.startsWith("pending")) ||
|
|
129
|
+
lines.some((line) => THROWAWAY.has(line)) ||
|
|
130
|
+
lines.some((line) => PLACEHOLDER_LINE_RE.test(line))
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** True when every non-blank line of `body` is a line the scaffold writes for `spec`. */
|
|
135
|
+
export function isScaffoldBody(body: string, spec: SectionSpec): boolean {
|
|
136
|
+
const lines = pySplitLines(body)
|
|
137
|
+
.map((line) => pyStrip(line))
|
|
138
|
+
.filter((line) => line !== "");
|
|
139
|
+
if (lines.length === 0) return false;
|
|
140
|
+
return lines.every((line) => spec.lines.some((template) => matchesTemplate(line, template)));
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** The state of one section, given the file's sections. */
|
|
144
|
+
export function sectionState(sections: Map<string, string>, spec: SectionSpec): SectionState {
|
|
145
|
+
const body = sections.get(spec.header);
|
|
146
|
+
if (body === undefined) return "missing";
|
|
147
|
+
if (isUnfilledBody(body)) return "unfilled";
|
|
148
|
+
if (isScaffoldBody(body, spec)) return "scaffold";
|
|
149
|
+
return "authored";
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const SPECS: Readonly<Record<ArtifactName, readonly SectionSpec[]>> = {
|
|
153
|
+
"index.md": STORY_INDEX_SECTIONS,
|
|
154
|
+
"plan.md": PLAN_SECTIONS,
|
|
155
|
+
"test-guide.md": TEST_GUIDE_SECTIONS,
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Which placeholder sections decide `name`. `plan.md` requires every one of its
|
|
160
|
+
* placeholder headings; the other two judge only the placeholder headings the file
|
|
161
|
+
* has, so a Driver's own structure is never called a scaffold.
|
|
162
|
+
*/
|
|
163
|
+
function judgedSections(name: ArtifactName, sections: Map<string, string>): SectionSpec[] {
|
|
164
|
+
const placeholders = SPECS[name].filter((spec) => spec.kind === "placeholder");
|
|
165
|
+
if (name === "plan.md") return placeholders;
|
|
166
|
+
return placeholders.filter((spec) => sections.has(spec.header));
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/** The `PLAN_SECTIONS` entry for `header`; a heading the table lacks is a default. */
|
|
170
|
+
function planSpec(header: string): SectionSpec {
|
|
171
|
+
return (
|
|
172
|
+
PLAN_SECTIONS.find((candidate) => candidate.header === header) ?? {
|
|
173
|
+
header,
|
|
174
|
+
kind: "default",
|
|
175
|
+
lines: [],
|
|
176
|
+
}
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/** What approval would refuse on in a `plan.md` whose sections are `sections`. */
|
|
181
|
+
function planToAuthor(sections: Map<string, string>): string[] {
|
|
182
|
+
return PLAN_APPROVAL_SECTIONS.filter(
|
|
183
|
+
(header) => sectionState(sections, planSpec(header)) !== "authored",
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/** The verdict for artifact text already read; `null` text means the file is missing. */
|
|
188
|
+
export function judgeArtifact(name: ArtifactName, text: string | null): ArtifactVerdict {
|
|
189
|
+
if (text === null) return { name, state: "missing", sections: [], toAuthor: [] };
|
|
190
|
+
const sections = levelTwoSections(text);
|
|
191
|
+
const verdicts = judgedSections(name, sections).map((spec) => ({
|
|
192
|
+
header: spec.header,
|
|
193
|
+
state: sectionState(sections, spec),
|
|
194
|
+
}));
|
|
195
|
+
const toAuthor =
|
|
196
|
+
name === "plan.md"
|
|
197
|
+
? planToAuthor(sections)
|
|
198
|
+
: verdicts.filter((verdict) => verdict.state !== "authored").map((verdict) => verdict.header);
|
|
199
|
+
// The word comes from the placeholder sections alone (D4): the required defaults
|
|
200
|
+
// lengthen the list, never turn a scaffold into a partly authored file.
|
|
201
|
+
const state: ArtifactState =
|
|
202
|
+
toAuthor.length === 0
|
|
203
|
+
? "authored"
|
|
204
|
+
: verdicts.some((verdict) => verdict.state === "authored")
|
|
205
|
+
? "partly_authored"
|
|
206
|
+
: verdicts.some((verdict) => verdict.state === "scaffold")
|
|
207
|
+
? "scaffold"
|
|
208
|
+
: "incomplete";
|
|
209
|
+
return { name, state, sections: verdicts, toAuthor };
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/** The verdict for the artifact at `path`. */
|
|
213
|
+
export function artifactState(name: ArtifactName, path: string): ArtifactVerdict {
|
|
214
|
+
if (!existsSync(path)) return judgeArtifact(name, null);
|
|
215
|
+
return judgeArtifact(name, readFileSync(path, "utf8"));
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* The sections of `plan.md` a Plan approval must see authored, on either route: the
|
|
220
|
+
* `toAuthor` list `build show` and the Plan checkpoint print for the same file (CR111
|
|
221
|
+
* D4). A missing file, or no file to read, leaves every one of them to write, which is
|
|
222
|
+
* what makes a receipt unusable before the Driver writes the Plan.
|
|
223
|
+
*/
|
|
224
|
+
export function planSectionsToAuthor(planPath: string | null): string[] {
|
|
225
|
+
if (planPath === null || !existsSync(planPath)) return [...PLAN_APPROVAL_SECTIONS];
|
|
226
|
+
return [...judgeArtifact("plan.md", readFileSync(planPath, "utf8")).toAuthor];
|
|
227
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// CR111 — the Plan-stage story files, judged and rendered once for every surface that
|
|
2
|
+
// names them.
|
|
3
|
+
//
|
|
4
|
+
// `build show` lists a story package's `index.md`, `plan.md`, and `test-guide.md`, each
|
|
5
|
+
// with its state and, while it is not authored, the sections still to write (CR112).
|
|
6
|
+
// The Plan checkpoint names the same three files the same way. Both import these lines
|
|
7
|
+
// from here, so the two surfaces cannot say different things about one file: the card
|
|
8
|
+
// does not reach into `build show`'s module, and neither keeps its own copy.
|
|
9
|
+
//
|
|
10
|
+
// The glyph carries only done or not; the word carries the state.
|
|
11
|
+
|
|
12
|
+
import { join } from "node:path";
|
|
13
|
+
import { CARD_WIDTH, cardText } from "../card.ts";
|
|
14
|
+
import { type ArtifactVerdict, artifactState, describeArtifactState } from "./scaffoldState.ts";
|
|
15
|
+
|
|
16
|
+
/** The artifacts Plan and Expand scaffold, in the order Plan writes them. */
|
|
17
|
+
export const PLAN_STAGE_ARTIFACTS = ["index.md", "plan.md", "test-guide.md"] as const;
|
|
18
|
+
|
|
19
|
+
/** The Plan-stage files of the package at `directory`, judged, in `PLAN_STAGE_ARTIFACTS` order. */
|
|
20
|
+
export function judgeStoryFiles(directory: string): ArtifactVerdict[] {
|
|
21
|
+
return PLAN_STAGE_ARTIFACTS.map((name) => artifactState(name, join(directory, name)));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const TO_AUTHOR = "to author: ";
|
|
25
|
+
const TO_AUTHOR_INDENT = " ";
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The sections still to write, wrapped BETWEEN headings, never inside one, with every
|
|
29
|
+
* row after the first starting under the first heading. A heading cut in two reads as
|
|
30
|
+
* two items: the first render printed `Navigator` over `Validation` (CR112's handoff
|
|
31
|
+
* review). The headings are the scaffold tables' own, all far shorter than a row.
|
|
32
|
+
*/
|
|
33
|
+
export function toAuthorLines(headers: readonly string[]): string[] {
|
|
34
|
+
const width = CARD_WIDTH - TO_AUTHOR_INDENT.length - TO_AUTHOR.length;
|
|
35
|
+
const rows: string[] = [];
|
|
36
|
+
let row = "";
|
|
37
|
+
headers.forEach((header, index) => {
|
|
38
|
+
const item = index < headers.length - 1 ? `${header},` : header;
|
|
39
|
+
const joined = row === "" ? item : `${row} ${item}`;
|
|
40
|
+
if (row !== "" && joined.length > width) {
|
|
41
|
+
rows.push(row);
|
|
42
|
+
row = item;
|
|
43
|
+
} else {
|
|
44
|
+
row = joined;
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
if (row !== "") rows.push(row);
|
|
48
|
+
const hanging = " ".repeat(TO_AUTHOR.length);
|
|
49
|
+
return rows.map((text, index) =>
|
|
50
|
+
cardText(`${TO_AUTHOR_INDENT}${index === 0 ? TO_AUTHOR : hanging}${text}`),
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** One file's card rows: its glyph, name, and state, then the sections still to write. */
|
|
55
|
+
export function storyFileLines(verdict: ArtifactVerdict): string[] {
|
|
56
|
+
const glyph = verdict.state === "authored" ? "✓" : "○";
|
|
57
|
+
return [
|
|
58
|
+
cardText(`${glyph} ${verdict.name} — ${describeArtifactState(verdict.state)}`),
|
|
59
|
+
...toAuthorLines(verdict.toAuthor),
|
|
60
|
+
];
|
|
61
|
+
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
// CV22.DS7.US8 plateau 3 — the story-package `index.md` scaffolds Expand writes.
|
|
2
|
+
//
|
|
3
|
+
// Port of the `_render_*_index` half of `src/memory/builder/lifecycle.py`.
|
|
4
|
+
//
|
|
5
|
+
// These bodies are written into the Navigator's repository and then read by
|
|
6
|
+
// humans, by `resolve_story_directory` (which locates a package by the heading
|
|
7
|
+
// these render), and by Expand's own candidate-table parser. So they are graded as
|
|
8
|
+
// bytes, not as structure: a changed dash, a dropped blank line, or a `—` turned
|
|
9
|
+
// into `--` moves a heading out of the grammar that finds it again.
|
|
10
|
+
//
|
|
11
|
+
// The Delivery Story scaffold is the one that closes the loop: it emits the
|
|
12
|
+
// canonical five-column candidate table, which is exactly the shape
|
|
13
|
+
// `parseCandidateStories` requires. A port that drifts here produces a package
|
|
14
|
+
// whose own Expand refuses it.
|
|
15
|
+
|
|
16
|
+
import { tableCell } from "../roadmapGrammar.ts";
|
|
17
|
+
import { storyFolderName } from "../storyPaths.ts";
|
|
18
|
+
import {
|
|
19
|
+
fill,
|
|
20
|
+
STORY_OUTCOME,
|
|
21
|
+
TECHNICAL_STORY_ACCEPTANCE,
|
|
22
|
+
TECHNICAL_STORY_STATEMENT,
|
|
23
|
+
USER_STORY_ACCEPTANCE,
|
|
24
|
+
USER_STORY_STATEMENT,
|
|
25
|
+
} from "./scaffoldSections.ts";
|
|
26
|
+
|
|
27
|
+
// Every sentence below is a template in `scaffoldSections.ts` (CR112): the reader
|
|
28
|
+
// that tells a scaffold from an authored file matches against the same lines these
|
|
29
|
+
// writers fill, so neither can drift from the other.
|
|
30
|
+
|
|
31
|
+
function fillLines(lines: readonly string[], title: string): string {
|
|
32
|
+
return lines.map((line) => fill(line, { title })).join("\n");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Python `_user_story_statement`. */
|
|
36
|
+
export function userStoryStatement(title: string): string {
|
|
37
|
+
return fillLines(USER_STORY_STATEMENT, title);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Python `_technical_story_statement`. */
|
|
41
|
+
export function technicalStoryStatement(title: string): string {
|
|
42
|
+
return fillLines(TECHNICAL_STORY_STATEMENT, title);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Python `_user_story_outcome`. */
|
|
46
|
+
export function userStoryOutcome(title: string): string {
|
|
47
|
+
return fill(STORY_OUTCOME, { title });
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Python `_render_delivery_story_index`. */
|
|
51
|
+
export function renderDeliveryStoryIndex(
|
|
52
|
+
code: string,
|
|
53
|
+
title: string,
|
|
54
|
+
recommendedCode: string,
|
|
55
|
+
recommendedTitle: string,
|
|
56
|
+
): string {
|
|
57
|
+
const link = `${storyFolderName(recommendedCode, recommendedTitle)}/index.md`;
|
|
58
|
+
return `[< Parent](../index.md)
|
|
59
|
+
|
|
60
|
+
# ${code} — ${title}
|
|
61
|
+
|
|
62
|
+
**Status:** 🟡 Planned
|
|
63
|
+
**Type:** Delivery Story
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Outcome
|
|
68
|
+
|
|
69
|
+
${title}
|
|
70
|
+
|
|
71
|
+
## Candidate Stories
|
|
72
|
+
|
|
73
|
+
| Code | Story | Type | Outcome | Status |
|
|
74
|
+
|------|-------|------|---------|--------|
|
|
75
|
+
| [${recommendedCode}](${link}) | ${tableCell(recommendedTitle)} | User Story | ${tableCell(userStoryOutcome(recommendedTitle))} | 🟡 Planned |
|
|
76
|
+
|
|
77
|
+
## Done Condition
|
|
78
|
+
|
|
79
|
+
The Delivery Story is done when child User/Technical Stories produce a coherent delivery outcome.
|
|
80
|
+
`;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Python `_render_technical_story_index`. */
|
|
84
|
+
export function renderTechnicalStoryIndex(code: string, title: string): string {
|
|
85
|
+
return `[< Parent](../index.md)
|
|
86
|
+
|
|
87
|
+
# ${code} — ${title}
|
|
88
|
+
|
|
89
|
+
**Status:** 🟡 Planned
|
|
90
|
+
**Type:** Technical Story
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Technical Story
|
|
95
|
+
|
|
96
|
+
${technicalStoryStatement(title)}
|
|
97
|
+
|
|
98
|
+
## Outcome
|
|
99
|
+
|
|
100
|
+
${userStoryOutcome(title)}
|
|
101
|
+
|
|
102
|
+
## Acceptance Behavior
|
|
103
|
+
|
|
104
|
+
\`\`\`text
|
|
105
|
+
${fillLines(TECHNICAL_STORY_ACCEPTANCE, title)}
|
|
106
|
+
\`\`\`
|
|
107
|
+
|
|
108
|
+
## Scope
|
|
109
|
+
|
|
110
|
+
- ${title}
|
|
111
|
+
|
|
112
|
+
## Out Of Scope
|
|
113
|
+
|
|
114
|
+
- Sibling Delivery Story scope.
|
|
115
|
+
|
|
116
|
+
## Validation
|
|
117
|
+
|
|
118
|
+
Navigator-visible validation route plus automated checks.
|
|
119
|
+
`;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** Python `_render_user_story_index`. */
|
|
123
|
+
export function renderUserStoryIndex(code: string, title: string): string {
|
|
124
|
+
return `[< Parent](../index.md)
|
|
125
|
+
|
|
126
|
+
# ${code} — ${title}
|
|
127
|
+
|
|
128
|
+
**Status:** 🟡 Planned
|
|
129
|
+
**Type:** User Story
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## User Story
|
|
134
|
+
|
|
135
|
+
${userStoryStatement(title)}
|
|
136
|
+
|
|
137
|
+
## Outcome
|
|
138
|
+
|
|
139
|
+
${userStoryOutcome(title)}
|
|
140
|
+
|
|
141
|
+
## Acceptance Behavior
|
|
142
|
+
|
|
143
|
+
\`\`\`text
|
|
144
|
+
${fillLines(USER_STORY_ACCEPTANCE, title)}
|
|
145
|
+
\`\`\`
|
|
146
|
+
|
|
147
|
+
## Scope
|
|
148
|
+
|
|
149
|
+
- ${title}
|
|
150
|
+
|
|
151
|
+
## Out Of Scope
|
|
152
|
+
|
|
153
|
+
- Sibling Delivery Story scope.
|
|
154
|
+
|
|
155
|
+
## Validation
|
|
156
|
+
|
|
157
|
+
Navigator-visible validation route plus automated checks.
|
|
158
|
+
`;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** Python `_render_story_index`: the level chooses the scaffold. */
|
|
162
|
+
export function renderStoryIndex(code: string, title: string, level: string): string {
|
|
163
|
+
return level === "technical_story"
|
|
164
|
+
? renderTechnicalStoryIndex(code, title)
|
|
165
|
+
: renderUserStoryIndex(code, title);
|
|
166
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// CR115 — the cadence a journey runs at, and the rows that print it.
|
|
2
|
+
//
|
|
3
|
+
// A journey's cadence changes what Plan does: under `accelerated`, Plan records a story
|
|
4
|
+
// preauthorization and the Driver continues into implementation without a Navigator
|
|
5
|
+
// turn. The cursor stores the profile and, for `autonomous`, its limits, and only the
|
|
6
|
+
// cursor sync report printed them, when the cadence was being changed. Every surface
|
|
7
|
+
// that orients the Navigator now prints them, from this module: the Builder resume and
|
|
8
|
+
// `build show` in their label-and-value pairs, the Builder orientation in its own rows.
|
|
9
|
+
//
|
|
10
|
+
// A cursor that stores no profile runs `stepwise`. The sync report and
|
|
11
|
+
// `continue-lifecycle` each held that default before; they read it here now.
|
|
12
|
+
//
|
|
13
|
+
// This module reads two fields and declares them itself, so it imports nothing from the
|
|
14
|
+
// cursor's persistence module, which imports it.
|
|
15
|
+
|
|
16
|
+
import { cardText, cardWrapped } from "./card.ts";
|
|
17
|
+
|
|
18
|
+
const FRAME_BLANK = cardText("");
|
|
19
|
+
|
|
20
|
+
/** The cursor fields the cadence is read from. */
|
|
21
|
+
export interface CadenceView {
|
|
22
|
+
readonly cadenceProfile: string | null;
|
|
23
|
+
readonly cadenceLimits: readonly string[];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** The profile the runtime applies: a cursor that stores none runs `stepwise`. */
|
|
27
|
+
export function effectiveCadenceProfile(cursor: CadenceView): string {
|
|
28
|
+
return cursor.cadenceProfile || "stepwise";
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The limits as one line, or `none`. They bound continuation only under `autonomous`,
|
|
33
|
+
* so only that profile prints them: a limit stored beside another profile bounds
|
|
34
|
+
* nothing, and printing it would say it did.
|
|
35
|
+
*/
|
|
36
|
+
function limitsUnder(cursor: CadenceView): string | null {
|
|
37
|
+
if (effectiveCadenceProfile(cursor) !== "autonomous") return null;
|
|
38
|
+
return cursor.cadenceLimits.length > 0 ? cursor.cadenceLimits.join(", ") : "none";
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* The resume's and `build show`'s rows: `cadence profile` and the profile, and under
|
|
43
|
+
* `autonomous`, `cadence limits` and the limits. With no cursor there is no cadence.
|
|
44
|
+
*/
|
|
45
|
+
export function cadenceCardLines(cursor: CadenceView | null): string[] {
|
|
46
|
+
if (cursor === null) return [cardText("cadence profile"), cardText("none")];
|
|
47
|
+
const lines = [cardText("cadence profile"), cardText(effectiveCadenceProfile(cursor))];
|
|
48
|
+
const limits = limitsUnder(cursor);
|
|
49
|
+
if (limits !== null) lines.push(FRAME_BLANK, cardText("cadence limits"), ...cardWrapped(limits));
|
|
50
|
+
return lines;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** The orientation's rows, in its `label: value` form, as it answers the Refinement question. */
|
|
54
|
+
export function cadenceOrientationLines(cursor: CadenceView): string[] {
|
|
55
|
+
const lines = cardWrapped(`cadence profile: ${effectiveCadenceProfile(cursor)}`);
|
|
56
|
+
const limits = limitsUnder(cursor);
|
|
57
|
+
if (limits !== null) lines.push(...cardWrapped(`cadence limits: ${limits}`));
|
|
58
|
+
return lines;
|
|
59
|
+
}
|