hammoc 1.4.0 → 1.6.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/README.md +428 -405
- package/bin/hammoc.js +0 -6
- package/package.json +100 -94
- package/packages/client/dist/assets/agentExampleHighlight-ltj9ce0U.js +1 -0
- package/packages/client/dist/assets/commandTokenHighlight-ji_ViMb4.js +1 -0
- package/packages/client/dist/assets/index-B-DiRGuz.js +2 -0
- package/packages/client/dist/assets/index-B09doO8H.js +139 -0
- package/packages/client/dist/assets/index-BT4RIi0U.js +1523 -0
- package/packages/client/dist/assets/index-DyNJ5jEW.css +32 -0
- package/packages/client/dist/assets/snippetTokenHighlight-CP3v4o2g.js +1 -0
- package/packages/client/dist/index.html +2 -2
- package/packages/client/dist/sw.js +1 -1
- package/packages/server/dist/app.d.ts.map +1 -1
- package/packages/server/dist/app.js +13 -21
- package/packages/server/dist/app.js.map +1 -1
- package/packages/server/dist/controllers/bmadCoreConfigController.d.ts +41 -0
- package/packages/server/dist/controllers/bmadCoreConfigController.d.ts.map +1 -0
- package/packages/server/dist/controllers/bmadCoreConfigController.js +172 -0
- package/packages/server/dist/controllers/bmadCoreConfigController.js.map +1 -0
- package/packages/server/dist/controllers/claudeMdController.d.ts +26 -0
- package/packages/server/dist/controllers/claudeMdController.d.ts.map +1 -0
- package/packages/server/dist/controllers/claudeMdController.js +158 -0
- package/packages/server/dist/controllers/claudeMdController.js.map +1 -0
- package/packages/server/dist/controllers/contextBuilderController.d.ts +43 -0
- package/packages/server/dist/controllers/contextBuilderController.d.ts.map +1 -0
- package/packages/server/dist/controllers/contextBuilderController.js +159 -0
- package/packages/server/dist/controllers/contextBuilderController.js.map +1 -0
- package/packages/server/dist/controllers/harnessAgentController.d.ts +35 -0
- package/packages/server/dist/controllers/harnessAgentController.d.ts.map +1 -0
- package/packages/server/dist/controllers/harnessAgentController.js +372 -0
- package/packages/server/dist/controllers/harnessAgentController.js.map +1 -0
- package/packages/server/dist/controllers/harnessBundleController.d.ts +37 -0
- package/packages/server/dist/controllers/harnessBundleController.d.ts.map +1 -0
- package/packages/server/dist/controllers/harnessBundleController.js +312 -0
- package/packages/server/dist/controllers/harnessBundleController.js.map +1 -0
- package/packages/server/dist/controllers/harnessCommandController.d.ts +35 -0
- package/packages/server/dist/controllers/harnessCommandController.d.ts.map +1 -0
- package/packages/server/dist/controllers/harnessCommandController.js +415 -0
- package/packages/server/dist/controllers/harnessCommandController.js.map +1 -0
- package/packages/server/dist/controllers/harnessController.d.ts +21 -0
- package/packages/server/dist/controllers/harnessController.d.ts.map +1 -0
- package/packages/server/dist/controllers/harnessController.js +176 -0
- package/packages/server/dist/controllers/harnessController.js.map +1 -0
- package/packages/server/dist/controllers/harnessHookController.d.ts +32 -0
- package/packages/server/dist/controllers/harnessHookController.d.ts.map +1 -0
- package/packages/server/dist/controllers/harnessHookController.js +406 -0
- package/packages/server/dist/controllers/harnessHookController.js.map +1 -0
- package/packages/server/dist/controllers/harnessLintController.d.ts +18 -0
- package/packages/server/dist/controllers/harnessLintController.d.ts.map +1 -0
- package/packages/server/dist/controllers/harnessLintController.js +72 -0
- package/packages/server/dist/controllers/harnessLintController.js.map +1 -0
- package/packages/server/dist/controllers/harnessMcpController.d.ts +28 -0
- package/packages/server/dist/controllers/harnessMcpController.d.ts.map +1 -0
- package/packages/server/dist/controllers/harnessMcpController.js +371 -0
- package/packages/server/dist/controllers/harnessMcpController.js.map +1 -0
- package/packages/server/dist/controllers/harnessPluginController.d.ts +17 -0
- package/packages/server/dist/controllers/harnessPluginController.d.ts.map +1 -0
- package/packages/server/dist/controllers/harnessPluginController.js +115 -0
- package/packages/server/dist/controllers/harnessPluginController.js.map +1 -0
- package/packages/server/dist/controllers/harnessShareScopeController.d.ts +24 -0
- package/packages/server/dist/controllers/harnessShareScopeController.d.ts.map +1 -0
- package/packages/server/dist/controllers/harnessShareScopeController.js +120 -0
- package/packages/server/dist/controllers/harnessShareScopeController.js.map +1 -0
- package/packages/server/dist/controllers/harnessSkillController.d.ts +32 -0
- package/packages/server/dist/controllers/harnessSkillController.d.ts.map +1 -0
- package/packages/server/dist/controllers/harnessSkillController.js +453 -0
- package/packages/server/dist/controllers/harnessSkillController.js.map +1 -0
- package/packages/server/dist/controllers/marketplaceController.d.ts +19 -0
- package/packages/server/dist/controllers/marketplaceController.d.ts.map +1 -0
- package/packages/server/dist/controllers/marketplaceController.js +74 -0
- package/packages/server/dist/controllers/marketplaceController.js.map +1 -0
- package/packages/server/dist/controllers/observabilityController.d.ts +32 -0
- package/packages/server/dist/controllers/observabilityController.d.ts.map +1 -0
- package/packages/server/dist/controllers/observabilityController.js +148 -0
- package/packages/server/dist/controllers/observabilityController.js.map +1 -0
- package/packages/server/dist/controllers/projectController.d.ts.map +1 -1
- package/packages/server/dist/controllers/projectController.js +11 -0
- package/packages/server/dist/controllers/projectController.js.map +1 -1
- package/packages/server/dist/controllers/snippetController.d.ts +35 -0
- package/packages/server/dist/controllers/snippetController.d.ts.map +1 -0
- package/packages/server/dist/controllers/snippetController.js +294 -0
- package/packages/server/dist/controllers/snippetController.js.map +1 -0
- package/packages/server/dist/handlers/streamCallbacks.d.ts +8 -0
- package/packages/server/dist/handlers/streamCallbacks.d.ts.map +1 -1
- package/packages/server/dist/handlers/streamCallbacks.js +8 -0
- package/packages/server/dist/handlers/streamCallbacks.js.map +1 -1
- package/packages/server/dist/handlers/websocket.d.ts +15 -0
- package/packages/server/dist/handlers/websocket.d.ts.map +1 -1
- package/packages/server/dist/handlers/websocket.js +103 -2
- package/packages/server/dist/handlers/websocket.js.map +1 -1
- package/packages/server/dist/index.js +5 -0
- package/packages/server/dist/index.js.map +1 -1
- package/packages/server/dist/locales/en/server.json +37 -4
- package/packages/server/dist/locales/es/server.json +0 -4
- package/packages/server/dist/locales/ja/server.json +0 -4
- package/packages/server/dist/locales/ko/server.json +0 -4
- package/packages/server/dist/locales/pt/server.json +0 -4
- package/packages/server/dist/locales/zh-CN/server.json +0 -4
- package/packages/server/dist/routes/harness.d.ts +8 -0
- package/packages/server/dist/routes/harness.d.ts.map +1 -0
- package/packages/server/dist/routes/harness.js +150 -0
- package/packages/server/dist/routes/harness.js.map +1 -0
- package/packages/server/dist/routes/projects.d.ts.map +1 -1
- package/packages/server/dist/routes/projects.js +5 -60
- package/packages/server/dist/routes/projects.js.map +1 -1
- package/packages/server/dist/routes/snippets.d.ts +14 -0
- package/packages/server/dist/routes/snippets.d.ts.map +1 -0
- package/packages/server/dist/routes/snippets.js +27 -0
- package/packages/server/dist/routes/snippets.js.map +1 -0
- package/packages/server/dist/services/bmadCoreConfigService.d.ts +86 -0
- package/packages/server/dist/services/bmadCoreConfigService.d.ts.map +1 -0
- package/packages/server/dist/services/bmadCoreConfigService.js +175 -0
- package/packages/server/dist/services/bmadCoreConfigService.js.map +1 -0
- package/packages/server/dist/services/bmadStatusService.d.ts +15 -2
- package/packages/server/dist/services/bmadStatusService.d.ts.map +1 -1
- package/packages/server/dist/services/bmadStatusService.js +146 -37
- package/packages/server/dist/services/bmadStatusService.js.map +1 -1
- package/packages/server/dist/services/chatService.d.ts +3 -0
- package/packages/server/dist/services/chatService.d.ts.map +1 -1
- package/packages/server/dist/services/chatService.js +28 -7
- package/packages/server/dist/services/chatService.js.map +1 -1
- package/packages/server/dist/services/claudeMdService.d.ts +48 -0
- package/packages/server/dist/services/claudeMdService.d.ts.map +1 -0
- package/packages/server/dist/services/claudeMdService.js +240 -0
- package/packages/server/dist/services/claudeMdService.js.map +1 -0
- package/packages/server/dist/services/commandService.d.ts +10 -0
- package/packages/server/dist/services/commandService.d.ts.map +1 -1
- package/packages/server/dist/services/commandService.js +129 -4
- package/packages/server/dist/services/commandService.js.map +1 -1
- package/packages/server/dist/services/contextBuilderScriptTemplate.d.ts +24 -0
- package/packages/server/dist/services/contextBuilderScriptTemplate.d.ts.map +1 -0
- package/packages/server/dist/services/contextBuilderScriptTemplate.js +181 -0
- package/packages/server/dist/services/contextBuilderScriptTemplate.js.map +1 -0
- package/packages/server/dist/services/contextBuilderService.d.ts +68 -0
- package/packages/server/dist/services/contextBuilderService.d.ts.map +1 -0
- package/packages/server/dist/services/contextBuilderService.js +345 -0
- package/packages/server/dist/services/contextBuilderService.js.map +1 -0
- package/packages/server/dist/services/fileWatcherService.d.ts +24 -0
- package/packages/server/dist/services/fileWatcherService.d.ts.map +1 -1
- package/packages/server/dist/services/fileWatcherService.js +232 -1
- package/packages/server/dist/services/fileWatcherService.js.map +1 -1
- package/packages/server/dist/services/harnessAgentService.d.ts +97 -0
- package/packages/server/dist/services/harnessAgentService.d.ts.map +1 -0
- package/packages/server/dist/services/harnessAgentService.js +988 -0
- package/packages/server/dist/services/harnessAgentService.js.map +1 -0
- package/packages/server/dist/services/harnessBundleService.d.ts +145 -0
- package/packages/server/dist/services/harnessBundleService.d.ts.map +1 -0
- package/packages/server/dist/services/harnessBundleService.js +1318 -0
- package/packages/server/dist/services/harnessBundleService.js.map +1 -0
- package/packages/server/dist/services/harnessCommandService.d.ts +81 -0
- package/packages/server/dist/services/harnessCommandService.d.ts.map +1 -0
- package/packages/server/dist/services/harnessCommandService.js +917 -0
- package/packages/server/dist/services/harnessCommandService.js.map +1 -0
- package/packages/server/dist/services/harnessHookService.d.ts +82 -0
- package/packages/server/dist/services/harnessHookService.d.ts.map +1 -0
- package/packages/server/dist/services/harnessHookService.js +1112 -0
- package/packages/server/dist/services/harnessHookService.js.map +1 -0
- package/packages/server/dist/services/harnessLintService.d.ts +49 -0
- package/packages/server/dist/services/harnessLintService.d.ts.map +1 -0
- package/packages/server/dist/services/harnessLintService.js +628 -0
- package/packages/server/dist/services/harnessLintService.js.map +1 -0
- package/packages/server/dist/services/harnessMcpService.d.ts +100 -0
- package/packages/server/dist/services/harnessMcpService.d.ts.map +1 -0
- package/packages/server/dist/services/harnessMcpService.js +884 -0
- package/packages/server/dist/services/harnessMcpService.js.map +1 -0
- package/packages/server/dist/services/harnessPluginService.d.ts +66 -0
- package/packages/server/dist/services/harnessPluginService.d.ts.map +1 -0
- package/packages/server/dist/services/harnessPluginService.js +559 -0
- package/packages/server/dist/services/harnessPluginService.js.map +1 -0
- package/packages/server/dist/services/harnessService.d.ts +40 -0
- package/packages/server/dist/services/harnessService.d.ts.map +1 -0
- package/packages/server/dist/services/harnessService.js +222 -0
- package/packages/server/dist/services/harnessService.js.map +1 -0
- package/packages/server/dist/services/harnessShareScopeService.d.ts +50 -0
- package/packages/server/dist/services/harnessShareScopeService.d.ts.map +1 -0
- package/packages/server/dist/services/harnessShareScopeService.js +158 -0
- package/packages/server/dist/services/harnessShareScopeService.js.map +1 -0
- package/packages/server/dist/services/harnessSkillService.d.ts +70 -0
- package/packages/server/dist/services/harnessSkillService.d.ts.map +1 -0
- package/packages/server/dist/services/harnessSkillService.js +636 -0
- package/packages/server/dist/services/harnessSkillService.js.map +1 -0
- package/packages/server/dist/services/issueService.d.ts.map +1 -1
- package/packages/server/dist/services/issueService.js +3 -1
- package/packages/server/dist/services/issueService.js.map +1 -1
- package/packages/server/dist/services/manualSyncService.d.ts +19 -0
- package/packages/server/dist/services/manualSyncService.d.ts.map +1 -0
- package/packages/server/dist/services/manualSyncService.js +110 -0
- package/packages/server/dist/services/manualSyncService.js.map +1 -0
- package/packages/server/dist/services/marketplaceService.d.ts +50 -0
- package/packages/server/dist/services/marketplaceService.d.ts.map +1 -0
- package/packages/server/dist/services/marketplaceService.js +326 -0
- package/packages/server/dist/services/marketplaceService.js.map +1 -0
- package/packages/server/dist/services/observabilityService.d.ts +87 -0
- package/packages/server/dist/services/observabilityService.d.ts.map +1 -0
- package/packages/server/dist/services/observabilityService.js +0 -0
- package/packages/server/dist/services/observabilityService.js.map +1 -0
- package/packages/server/dist/services/queueService.d.ts.map +1 -1
- package/packages/server/dist/services/queueService.js +48 -2
- package/packages/server/dist/services/queueService.js.map +1 -1
- package/packages/server/dist/services/sessionService.d.ts +16 -0
- package/packages/server/dist/services/sessionService.d.ts.map +1 -1
- package/packages/server/dist/services/sessionService.js +125 -0
- package/packages/server/dist/services/sessionService.js.map +1 -1
- package/packages/server/dist/services/snippetService.d.ts +54 -0
- package/packages/server/dist/services/snippetService.d.ts.map +1 -0
- package/packages/server/dist/services/snippetService.js +371 -0
- package/packages/server/dist/services/snippetService.js.map +1 -0
- package/packages/server/dist/services/tokenCountService.d.ts +71 -0
- package/packages/server/dist/services/tokenCountService.d.ts.map +1 -0
- package/packages/server/dist/services/tokenCountService.js +313 -0
- package/packages/server/dist/services/tokenCountService.js.map +1 -0
- package/packages/server/dist/services/utils/applyYamlFrontmatterPatch.d.ts +46 -0
- package/packages/server/dist/services/utils/applyYamlFrontmatterPatch.d.ts.map +1 -0
- package/packages/server/dist/services/utils/applyYamlFrontmatterPatch.js +125 -0
- package/packages/server/dist/services/utils/applyYamlFrontmatterPatch.js.map +1 -0
- package/packages/server/dist/snippets/apply-qa-fixes +7 -5
- package/packages/server/dist/snippets/qa-review +5 -1
- package/packages/server/dist/snippets/split-commit +9 -0
- package/packages/server/dist/utils/applySecretsPolicy.d.ts +53 -0
- package/packages/server/dist/utils/applySecretsPolicy.d.ts.map +1 -0
- package/packages/server/dist/utils/applySecretsPolicy.js +204 -0
- package/packages/server/dist/utils/applySecretsPolicy.js.map +1 -0
- package/packages/server/dist/utils/assertNoSecretOnShared.d.ts +40 -0
- package/packages/server/dist/utils/assertNoSecretOnShared.d.ts.map +1 -0
- package/packages/server/dist/utils/assertNoSecretOnShared.js +47 -0
- package/packages/server/dist/utils/assertNoSecretOnShared.js.map +1 -0
- package/packages/server/dist/utils/assertSafeBundlePath.d.ts +29 -0
- package/packages/server/dist/utils/assertSafeBundlePath.d.ts.map +1 -0
- package/packages/server/dist/utils/assertSafeBundlePath.js +53 -0
- package/packages/server/dist/utils/assertSafeBundlePath.js.map +1 -0
- package/packages/server/dist/utils/bundledBinaryModelSupport.d.ts +7 -0
- package/packages/server/dist/utils/bundledBinaryModelSupport.d.ts.map +1 -0
- package/packages/server/dist/utils/bundledBinaryModelSupport.js +107 -0
- package/packages/server/dist/utils/bundledBinaryModelSupport.js.map +1 -0
- package/packages/server/dist/utils/effortUtils.d.ts +2 -2
- package/packages/server/dist/utils/effortUtils.js +5 -5
- package/packages/server/dist/utils/effortUtils.js.map +1 -1
- package/packages/server/dist/utils/errors.d.ts +1 -0
- package/packages/server/dist/utils/errors.d.ts.map +1 -1
- package/packages/server/dist/utils/errors.js +17 -0
- package/packages/server/dist/utils/errors.js.map +1 -1
- package/packages/server/dist/utils/gitignoreFilter.d.ts +23 -0
- package/packages/server/dist/utils/gitignoreFilter.d.ts.map +1 -0
- package/packages/server/dist/utils/gitignoreFilter.js +42 -0
- package/packages/server/dist/utils/gitignoreFilter.js.map +1 -0
- package/packages/server/dist/utils/harnessBundleSchema.d.ts +107 -0
- package/packages/server/dist/utils/harnessBundleSchema.d.ts.map +1 -0
- package/packages/server/dist/utils/harnessBundleSchema.js +89 -0
- package/packages/server/dist/utils/harnessBundleSchema.js.map +1 -0
- package/packages/server/dist/utils/harnessPaths.d.ts +74 -0
- package/packages/server/dist/utils/harnessPaths.d.ts.map +1 -0
- package/packages/server/dist/utils/harnessPaths.js +247 -0
- package/packages/server/dist/utils/harnessPaths.js.map +1 -0
- package/packages/server/dist/utils/secretHeuristic.d.ts +72 -0
- package/packages/server/dist/utils/secretHeuristic.d.ts.map +1 -0
- package/packages/server/dist/utils/secretHeuristic.js +163 -0
- package/packages/server/dist/utils/secretHeuristic.js.map +1 -0
- package/packages/server/dist/utils/secretPlaceholderNamer.d.ts +41 -0
- package/packages/server/dist/utils/secretPlaceholderNamer.d.ts.map +1 -0
- package/packages/server/dist/utils/secretPlaceholderNamer.js +81 -0
- package/packages/server/dist/utils/secretPlaceholderNamer.js.map +1 -0
- package/packages/server/dist/utils/serverPathResolver.d.ts +29 -0
- package/packages/server/dist/utils/serverPathResolver.d.ts.map +1 -0
- package/packages/server/dist/utils/serverPathResolver.js +59 -0
- package/packages/server/dist/utils/serverPathResolver.js.map +1 -0
- package/packages/server/dist/utils/snippetPaths.d.ts +61 -0
- package/packages/server/dist/utils/snippetPaths.d.ts.map +1 -0
- package/packages/server/dist/utils/snippetPaths.js +123 -0
- package/packages/server/dist/utils/snippetPaths.js.map +1 -0
- package/packages/server/dist/utils/structuredEditor.d.ts +34 -0
- package/packages/server/dist/utils/structuredEditor.d.ts.map +1 -0
- package/packages/server/dist/utils/structuredEditor.js +111 -0
- package/packages/server/dist/utils/structuredEditor.js.map +1 -0
- package/packages/server/package.json +6 -2
- package/packages/server/resources/internals/INDEX.md +25 -0
- package/packages/server/resources/internals/bmad-qa-fix-marker.md +32 -0
- package/packages/server/resources/internals/harness-files.md +85 -0
- package/packages/server/resources/internals/image-storage.md +43 -0
- package/packages/server/resources/internals/observability-storage.md +23 -0
- package/packages/server/resources/manual/01-getting-started.md +104 -0
- package/packages/server/resources/manual/02-chat.md +285 -0
- package/packages/server/resources/manual/03-sessions.md +48 -0
- package/packages/server/resources/manual/04-slash-commands-favorites.md +152 -0
- package/packages/server/resources/manual/05-projects.md +76 -0
- package/packages/server/resources/manual/06-file-explorer-editor.md +90 -0
- package/packages/server/resources/manual/07-git.md +94 -0
- package/packages/server/resources/manual/08-terminal.md +59 -0
- package/packages/server/resources/manual/09-queue-runner.md +262 -0
- package/packages/server/resources/manual/10-project-board.md +194 -0
- package/packages/server/resources/manual/11-bmad-method-integration.md +130 -0
- package/packages/server/resources/manual/12-harness-workbench.md +256 -0
- package/packages/server/resources/manual/13-settings.md +241 -0
- package/packages/server/resources/manual/14-keyboard-shortcuts.md +68 -0
- package/packages/server/resources/manual/15-environment-variables.md +28 -0
- package/packages/server/resources/manual/16-troubleshooting.md +110 -0
- package/packages/server/resources/manual/INDEX.md +60 -0
- package/packages/shared/dist/index.d.ts +7 -0
- package/packages/shared/dist/index.d.ts.map +1 -1
- package/packages/shared/dist/index.js +14 -0
- package/packages/shared/dist/index.js.map +1 -1
- package/packages/shared/dist/types/bmadCoreConfig.d.ts +71 -0
- package/packages/shared/dist/types/bmadCoreConfig.d.ts.map +1 -0
- package/packages/shared/dist/types/bmadCoreConfig.js +30 -0
- package/packages/shared/dist/types/bmadCoreConfig.js.map +1 -0
- package/packages/shared/dist/types/bmadStatus.d.ts +10 -0
- package/packages/shared/dist/types/bmadStatus.d.ts.map +1 -1
- package/packages/shared/dist/types/bmadStatus.js.map +1 -1
- package/packages/shared/dist/types/board.d.ts +6 -0
- package/packages/shared/dist/types/board.d.ts.map +1 -1
- package/packages/shared/dist/types/command.d.ts +3 -3
- package/packages/shared/dist/types/command.d.ts.map +1 -1
- package/packages/shared/dist/types/contextBuilder.d.ts +102 -0
- package/packages/shared/dist/types/contextBuilder.d.ts.map +1 -0
- package/packages/shared/dist/types/contextBuilder.js +55 -0
- package/packages/shared/dist/types/contextBuilder.js.map +1 -0
- package/packages/shared/dist/types/harness.d.ts +1211 -0
- package/packages/shared/dist/types/harness.d.ts.map +1 -0
- package/packages/shared/dist/types/harness.js +107 -0
- package/packages/shared/dist/types/harness.js.map +1 -0
- package/packages/shared/dist/types/harnessBundle.d.ts +205 -0
- package/packages/shared/dist/types/harnessBundle.d.ts.map +1 -0
- package/packages/shared/dist/types/harnessBundle.js +18 -0
- package/packages/shared/dist/types/harnessBundle.js.map +1 -0
- package/packages/shared/dist/types/marketplace.d.ts +83 -0
- package/packages/shared/dist/types/marketplace.d.ts.map +1 -0
- package/packages/shared/dist/types/marketplace.js +18 -0
- package/packages/shared/dist/types/marketplace.js.map +1 -0
- package/packages/shared/dist/types/observability.d.ts +148 -0
- package/packages/shared/dist/types/observability.d.ts.map +1 -0
- package/packages/shared/dist/types/observability.js +24 -0
- package/packages/shared/dist/types/observability.js.map +1 -0
- package/packages/shared/dist/types/preferences.d.ts +4 -0
- package/packages/shared/dist/types/preferences.d.ts.map +1 -1
- package/packages/shared/dist/types/preferences.js.map +1 -1
- package/packages/shared/dist/types/queue.d.ts +9 -0
- package/packages/shared/dist/types/queue.d.ts.map +1 -1
- package/packages/shared/dist/types/sdk.d.ts +1 -1
- package/packages/shared/dist/types/sdk.d.ts.map +1 -1
- package/packages/shared/dist/types/sdk.js +1 -1
- package/packages/shared/dist/types/sdk.js.map +1 -1
- package/packages/shared/dist/types/websocket.d.ts +10 -0
- package/packages/shared/dist/types/websocket.d.ts.map +1 -1
- package/packages/shared/dist/utils/markdownSections.d.ts +50 -0
- package/packages/shared/dist/utils/markdownSections.d.ts.map +1 -0
- package/packages/shared/dist/utils/markdownSections.js +111 -0
- package/packages/shared/dist/utils/markdownSections.js.map +1 -0
- package/packages/shared/dist/utils/queueParser.d.ts.map +1 -1
- package/packages/shared/dist/utils/queueParser.js +104 -0
- package/packages/shared/dist/utils/queueParser.js.map +1 -1
- package/scripts/build-manual-shards.mjs +100 -0
- package/packages/client/dist/assets/index-6jREnVYd.js +0 -2
- package/packages/client/dist/assets/index-BFF0iqyW.css +0 -32
- package/packages/client/dist/assets/index-BcI4y-fU.js +0 -1454
|
@@ -318,10 +318,6 @@
|
|
|
318
318
|
"invalidChatId": "유효하지 않은 Chat ID입니다.",
|
|
319
319
|
"writeError": "Telegram 설정 저장에 실패했습니다.",
|
|
320
320
|
"testError": "테스트 알림 전송 중 서버 오류가 발생했습니다."
|
|
321
|
-
},
|
|
322
|
-
"rateLimit": {
|
|
323
|
-
"projectCreate": "프로젝트 생성 요청이 너무 많습니다. 잠시 후 다시 시도해 주세요.",
|
|
324
|
-
"pathValidation": "경로 검증 요청이 너무 많습니다. 잠시 후 다시 시도해 주세요."
|
|
325
321
|
}
|
|
326
322
|
}
|
|
327
323
|
}
|
|
@@ -307,10 +307,6 @@
|
|
|
307
307
|
"invalidChatId": "Chat ID inválido.",
|
|
308
308
|
"writeError": "Erro ao salvar configurações do Telegram.",
|
|
309
309
|
"testError": "Erro do servidor ao enviar notificação de teste."
|
|
310
|
-
},
|
|
311
|
-
"rateLimit": {
|
|
312
|
-
"projectCreate": "Muitas solicitações de criação de projeto. Tente novamente mais tarde.",
|
|
313
|
-
"pathValidation": "Muitas solicitações de validação de caminho. Tente novamente mais tarde."
|
|
314
310
|
}
|
|
315
311
|
}
|
|
316
312
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Story 28.0.5: Harness workbench routes.
|
|
3
|
+
* Mounted at /api/harness — independent of /api/projects because the user
|
|
4
|
+
* scope (~/.claude) is not nested under any project.
|
|
5
|
+
*/
|
|
6
|
+
declare const router: import("express-serve-static-core").Router;
|
|
7
|
+
export default router;
|
|
8
|
+
//# sourceMappingURL=harness.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harness.d.ts","sourceRoot":"","sources":["../../src/routes/harness.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAoBH,QAAA,MAAM,MAAM,4CAAW,CAAC;AA2JxB,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Story 28.0.5: Harness workbench routes.
|
|
3
|
+
* Mounted at /api/harness — independent of /api/projects because the user
|
|
4
|
+
* scope (~/.claude) is not nested under any project.
|
|
5
|
+
*/
|
|
6
|
+
import { Router } from 'express';
|
|
7
|
+
import express from 'express';
|
|
8
|
+
import { harnessController } from '../controllers/harnessController.js';
|
|
9
|
+
import { harnessPluginController } from '../controllers/harnessPluginController.js';
|
|
10
|
+
import { harnessSkillController } from '../controllers/harnessSkillController.js';
|
|
11
|
+
import { harnessMcpController } from '../controllers/harnessMcpController.js';
|
|
12
|
+
import { harnessHookController } from '../controllers/harnessHookController.js';
|
|
13
|
+
import { harnessCommandController } from '../controllers/harnessCommandController.js';
|
|
14
|
+
import { harnessAgentController } from '../controllers/harnessAgentController.js';
|
|
15
|
+
import { claudeMdController } from '../controllers/claudeMdController.js';
|
|
16
|
+
import { harnessShareScopeController } from '../controllers/harnessShareScopeController.js';
|
|
17
|
+
import { harnessLintController } from '../controllers/harnessLintController.js';
|
|
18
|
+
import { harnessBundleController, handleBundleUpload } from '../controllers/harnessBundleController.js';
|
|
19
|
+
import { bmadCoreConfigController } from '../controllers/bmadCoreConfigController.js';
|
|
20
|
+
import { contextBuilderController } from '../controllers/contextBuilderController.js';
|
|
21
|
+
import { observabilityController } from '../controllers/observabilityController.js';
|
|
22
|
+
import { marketplaceController } from '../controllers/marketplaceController.js';
|
|
23
|
+
const router = Router();
|
|
24
|
+
// Same body size as fileSystem routes (JSON envelopes can carry ~1MB source files).
|
|
25
|
+
const largeBodyParser = express.json({ limit: '5mb' });
|
|
26
|
+
router.get('/list', harnessController.list);
|
|
27
|
+
router.get('/read', harnessController.read);
|
|
28
|
+
router.put('/write', largeBodyParser, harnessController.write);
|
|
29
|
+
router.post('/patch-structured', largeBodyParser, harnessController.patchStructured);
|
|
30
|
+
// Story 28.1 — plugin list / toggle (user scope only)
|
|
31
|
+
router.get('/plugins', harnessPluginController.list);
|
|
32
|
+
router.post('/plugins/toggle', express.json({ limit: '32kb' }), harnessPluginController.toggle);
|
|
33
|
+
// Story 28.2 — skill list / read / update / copy + per-skill bundle file edit.
|
|
34
|
+
// The bundle routes are mounted *before* `/skills/:name` so the splat segment
|
|
35
|
+
// (`/bundle/*`) is matched first; otherwise Express would treat "bundle" as a
|
|
36
|
+
// `:name` value.
|
|
37
|
+
router.post('/skills/copy', largeBodyParser, harnessSkillController.copy);
|
|
38
|
+
router.get('/skills', harnessSkillController.list);
|
|
39
|
+
router.get('/skills/:name/bundle/*', harnessSkillController.readBundle);
|
|
40
|
+
router.put('/skills/:name/bundle/*', largeBodyParser, harnessSkillController.writeBundle);
|
|
41
|
+
router.get('/skills/:name', harnessSkillController.read);
|
|
42
|
+
router.put('/skills/:name', largeBodyParser, harnessSkillController.update);
|
|
43
|
+
// Story 28.3 — MCP list / read / update / copy / delete.
|
|
44
|
+
// `copy` lives above `/mcps/:name` so Express prefers the literal segment.
|
|
45
|
+
router.post('/mcps/copy', largeBodyParser, harnessMcpController.copy);
|
|
46
|
+
router.get('/mcps', harnessMcpController.list);
|
|
47
|
+
router.get('/mcps/:name', harnessMcpController.read);
|
|
48
|
+
router.put('/mcps/:name', largeBodyParser, harnessMcpController.update);
|
|
49
|
+
router.delete('/mcps/:name', largeBodyParser, harnessMcpController.delete);
|
|
50
|
+
// Story 28.4 — Hook list / read / create / update / copy / delete.
|
|
51
|
+
// `copy` and the splat-free POST live above `/hooks/:event/...` so Express
|
|
52
|
+
// prefers the literal segments.
|
|
53
|
+
router.post('/hooks/copy', largeBodyParser, harnessHookController.copy);
|
|
54
|
+
router.post('/hooks', largeBodyParser, harnessHookController.create);
|
|
55
|
+
router.get('/hooks', harnessHookController.list);
|
|
56
|
+
router.get('/hooks/:event/:groupIndex/:hookIndex', harnessHookController.read);
|
|
57
|
+
router.put('/hooks/:event/:groupIndex/:hookIndex', largeBodyParser, harnessHookController.update);
|
|
58
|
+
router.delete('/hooks/:event/:groupIndex/:hookIndex', largeBodyParser, harnessHookController.delete);
|
|
59
|
+
// Story 28.5 — Slash command list / read / create / update / copy / copy-directory / delete.
|
|
60
|
+
// path-as-glob — params[0] holds the full relative path (e.g. "BMad/agents/sm.md").
|
|
61
|
+
// Literal segments (`/commands/copy`, `/commands/copy-directory`) live above the
|
|
62
|
+
// splat so Express prefers them.
|
|
63
|
+
router.post('/commands/copy-directory', largeBodyParser, harnessCommandController.copyDirectory);
|
|
64
|
+
router.post('/commands/copy', largeBodyParser, harnessCommandController.copy);
|
|
65
|
+
// Story 30.7 (Task B.2) — env-ref replace endpoint. Must live above the
|
|
66
|
+
// splat so Express does not treat `replace-secret-with-env-ref` as a
|
|
67
|
+
// command relative path.
|
|
68
|
+
router.post('/commands/replace-secret-with-env-ref', largeBodyParser, harnessCommandController.replaceSecretWithEnvRef);
|
|
69
|
+
router.post('/commands', largeBodyParser, harnessCommandController.create);
|
|
70
|
+
router.get('/commands', harnessCommandController.list);
|
|
71
|
+
router.get('/commands/*', harnessCommandController.read);
|
|
72
|
+
router.put('/commands/*', largeBodyParser, harnessCommandController.update);
|
|
73
|
+
router.delete('/commands/*', largeBodyParser, harnessCommandController.delete);
|
|
74
|
+
// Story 28.6 — Sub-agent list / read / create / update / copy / delete.
|
|
75
|
+
// Single-segment :name path param (flat-only — no recursive subdirectories per AC1.a).
|
|
76
|
+
// Literal `/agents/copy` and the splat-free POST live above the dynamic
|
|
77
|
+
// `:name` segment so Express prefers them.
|
|
78
|
+
router.post('/agents/copy', largeBodyParser, harnessAgentController.copy);
|
|
79
|
+
// Story 30.7 (Task B.2) — env-ref replace endpoint. Lives above the dynamic
|
|
80
|
+
// `:name` so Express does not match the literal as an agent name.
|
|
81
|
+
router.post('/agents/replace-secret-with-env-ref', largeBodyParser, harnessAgentController.replaceSecretWithEnvRef);
|
|
82
|
+
router.post('/agents', largeBodyParser, harnessAgentController.create);
|
|
83
|
+
router.get('/agents', harnessAgentController.list);
|
|
84
|
+
router.get('/agents/:name', harnessAgentController.read);
|
|
85
|
+
router.put('/agents/:name', largeBodyParser, harnessAgentController.update);
|
|
86
|
+
router.delete('/agents/:name', largeBodyParser, harnessAgentController.delete);
|
|
87
|
+
// Story 29.1 — CLAUDE.md (free-edit memory layer): two files only
|
|
88
|
+
// (project root + global). POST is a distinct create-empty path that fails
|
|
89
|
+
// with 409 if the file already exists (PUT-with-empty-content overwrite is
|
|
90
|
+
// intentionally a separate code path so client intent is preserved).
|
|
91
|
+
router.get('/claude-md', claudeMdController.read);
|
|
92
|
+
router.put('/claude-md', largeBodyParser, claudeMdController.write);
|
|
93
|
+
router.post('/claude-md', largeBodyParser, claudeMdController.create);
|
|
94
|
+
// Story 30.1 — Share-scope evaluator: classifies harness files as
|
|
95
|
+
// shared / local / fullyIgnored from `.gitignore` and derives the project
|
|
96
|
+
// Mode A/B verdict. Project scope only — `.gitignore` is irrelevant for
|
|
97
|
+
// the user-scope (`~/.claude`) tree.
|
|
98
|
+
router.get('/share-scope', harnessShareScopeController.evaluate);
|
|
99
|
+
// Story 30.7 (Task D.3) — append a pattern to the project `.gitignore`
|
|
100
|
+
// (idempotent). Used by the `SecretOnSharedDialog → Move to local` flow
|
|
101
|
+
// when the sibling pre-check detects `**/.claude/**/*.local.*` is missing.
|
|
102
|
+
router.post('/share-scope/:projectSlug/append-gitignore', express.json({ limit: '4kb' }), harnessShareScopeController.appendGitignore);
|
|
103
|
+
// Story 30.2 — Static harness lint: 7 rules across the 5 harness domains
|
|
104
|
+
// (skill / mcp / hook / command / agent). Returns LintIssue[] + the user's
|
|
105
|
+
// effective rule preferences (defaults merged with ~/.hammoc/preferences.json).
|
|
106
|
+
router.get('/lint', harnessLintController.evaluate);
|
|
107
|
+
// Story 30.5 — Harness Export/Import bundle: 4 endpoints providing the
|
|
108
|
+
// server-side single source of truth for serializing a project's harness
|
|
109
|
+
// surface into a ZIP + manifest.json and back. Multipart upload is only
|
|
110
|
+
// required by the import-preview endpoint; the other three use JSON bodies.
|
|
111
|
+
router.post('/bundle/export', largeBodyParser, harnessBundleController.export);
|
|
112
|
+
router.post('/bundle/import/preview', handleBundleUpload, harnessBundleController.importPreview);
|
|
113
|
+
router.post('/bundle/import/apply', largeBodyParser, harnessBundleController.importApply);
|
|
114
|
+
router.get('/bundle/plugin-deps', harnessBundleController.pluginDeps);
|
|
115
|
+
// Story 31.1 — BMad core-config editor: read / AST-patch / raw-overwrite of a
|
|
116
|
+
// single project's `.bmad-core/core-config.yaml` (BMad projects only — the nav
|
|
117
|
+
// gate is client-side via `isBmadProject`). The `/raw` segment lives above the
|
|
118
|
+
// bare `:projectSlug` PATCH so Express does not treat `raw` as a slug value.
|
|
119
|
+
router.get('/bmad-config/:projectSlug', bmadCoreConfigController.read);
|
|
120
|
+
router.put('/bmad-config/:projectSlug/raw', largeBodyParser, bmadCoreConfigController.writeRaw);
|
|
121
|
+
router.patch('/bmad-config/:projectSlug', largeBodyParser, bmadCoreConfigController.patch);
|
|
122
|
+
// Story 31.2 — SessionStart context-builder: read / save+generate / disable the
|
|
123
|
+
// `.hammoc/context-builder.json` manifest and its generated `.mjs` + settings
|
|
124
|
+
// entry. Available on ALL projects (no BMad gate). The `/disable` segment lives
|
|
125
|
+
// above the bare `:projectSlug` PUT so Express does not treat `disable` as a
|
|
126
|
+
// slug value.
|
|
127
|
+
router.get('/context-builder/:projectSlug', contextBuilderController.read);
|
|
128
|
+
router.post('/context-builder/:projectSlug/disable', largeBodyParser, contextBuilderController.disable);
|
|
129
|
+
router.put('/context-builder/:projectSlug', largeBodyParser, contextBuilderController.write);
|
|
130
|
+
// Story 31.3 — Observability: MCP call log (read-only aggregates + timeline) +
|
|
131
|
+
// token attribution + count_tokens proxy + global tokenizer preference.
|
|
132
|
+
// Available on ALL projects (no gate). The global `/tokenizer-pref` (no
|
|
133
|
+
// projectSlug) is mounted ABOVE the `:projectSlug` routes so Express does not
|
|
134
|
+
// treat `tokenizer-pref` as a slug. The MCP log has no write endpoint —
|
|
135
|
+
// records are appended by the streamCallbacks recorder.
|
|
136
|
+
const smallBodyParser = express.json({ limit: '32kb' });
|
|
137
|
+
router.get('/observability/tokenizer-pref', observabilityController.getTokenizerPref);
|
|
138
|
+
router.put('/observability/tokenizer-pref', smallBodyParser, observabilityController.setTokenizerPref);
|
|
139
|
+
router.get('/observability/:projectSlug/mcp-calls', observabilityController.mcpCalls);
|
|
140
|
+
router.get('/observability/:projectSlug/token-attribution', observabilityController.tokenAttribution);
|
|
141
|
+
router.post('/observability/:projectSlug/exact-count', smallBodyParser, observabilityController.exactCount);
|
|
142
|
+
// Story 31.4 — Plugin marketplace catalog (read-only). Single GET endpoint:
|
|
143
|
+
// the unified `plugins[]` catalog across registered marketplaces + installed
|
|
144
|
+
// join + per-market partial failures + installed_plugins.json format warning.
|
|
145
|
+
// No install/add POST — direct-install automation was dropped after spike #2
|
|
146
|
+
// (negative); installs are copy-only command guides (see sdk-upstream-issues.md
|
|
147
|
+
// §17·§18).
|
|
148
|
+
router.get('/marketplace/:projectSlug/catalog', marketplaceController.catalog);
|
|
149
|
+
export default router;
|
|
150
|
+
//# sourceMappingURL=harness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harness.js","sourceRoot":"","sources":["../../src/routes/harness.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"projects.d.ts","sourceRoot":"","sources":["../../src/routes/projects.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,QAAA,MAAM,MAAM,4CAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"projects.d.ts","sourceRoot":"","sources":["../../src/routes/projects.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,QAAA,MAAM,MAAM,4CAAW,CAAC;AAgCxB,eAAe,MAAM,CAAC"}
|
|
@@ -7,69 +7,14 @@
|
|
|
7
7
|
import { Router } from 'express';
|
|
8
8
|
import { projectController } from '../controllers/projectController.js';
|
|
9
9
|
const router = Router();
|
|
10
|
-
const rateLimitStore = new Map();
|
|
11
|
-
/**
|
|
12
|
-
* Cleanup expired rate limit records periodically
|
|
13
|
-
* Runs every 5 minutes to prevent memory growth
|
|
14
|
-
*/
|
|
15
|
-
const CLEANUP_INTERVAL_MS = 5 * 60 * 1000; // 5 minutes
|
|
16
|
-
const RECORD_TTL_MS = 2 * 60 * 1000; // Keep records for 2 minutes after window expires
|
|
17
|
-
function cleanupExpiredRecords() {
|
|
18
|
-
const now = Date.now();
|
|
19
|
-
for (const [ip, record] of rateLimitStore.entries()) {
|
|
20
|
-
// Remove records that are older than TTL
|
|
21
|
-
if (now - record.windowStart > RECORD_TTL_MS) {
|
|
22
|
-
rateLimitStore.delete(ip);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
// Start periodic cleanup
|
|
27
|
-
const cleanupInterval = setInterval(cleanupExpiredRecords, CLEANUP_INTERVAL_MS);
|
|
28
|
-
// Cleanup on process exit (for graceful shutdown)
|
|
29
|
-
if (typeof process !== 'undefined' && process.on) {
|
|
30
|
-
process.on('beforeExit', () => {
|
|
31
|
-
clearInterval(cleanupInterval);
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
function createRateLimiter(maxRequests, windowMs) {
|
|
35
|
-
return (req, res, next) => {
|
|
36
|
-
const ip = req.ip || req.socket.remoteAddress || 'unknown';
|
|
37
|
-
const now = Date.now();
|
|
38
|
-
const record = rateLimitStore.get(ip);
|
|
39
|
-
if (!record || now - record.windowStart > windowMs) {
|
|
40
|
-
// New window
|
|
41
|
-
rateLimitStore.set(ip, { count: 1, windowStart: now });
|
|
42
|
-
next();
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
if (record.count >= maxRequests) {
|
|
46
|
-
const retryAfter = Math.ceil((record.windowStart + windowMs - now) / 1000);
|
|
47
|
-
res.status(429).json({
|
|
48
|
-
error: {
|
|
49
|
-
code: 'RATE_LIMIT_EXCEEDED',
|
|
50
|
-
message: maxRequests === 10
|
|
51
|
-
? req.t('preferences.rateLimit.projectCreate')
|
|
52
|
-
: req.t('preferences.rateLimit.pathValidation'),
|
|
53
|
-
details: { retryAfter },
|
|
54
|
-
},
|
|
55
|
-
});
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
record.count++;
|
|
59
|
-
next();
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
// Rate limiters
|
|
63
|
-
const createProjectLimiter = createRateLimiter(10, 60 * 1000); // 10 requests per minute
|
|
64
|
-
const validatePathLimiter = createRateLimiter(30, 60 * 1000); // 30 requests per minute
|
|
65
10
|
// GET /api/projects - List all projects
|
|
66
11
|
router.get('/', projectController.list);
|
|
67
|
-
// POST /api/projects - Create new project
|
|
68
|
-
router.post('/',
|
|
12
|
+
// POST /api/projects - Create new project
|
|
13
|
+
router.post('/', projectController.create);
|
|
69
14
|
// GET /api/projects/bmad-versions - List available BMad method versions
|
|
70
15
|
router.get('/bmad-versions', projectController.bmadVersions);
|
|
71
16
|
// POST /api/projects/:projectSlug/setup-bmad - Setup BMad for existing project
|
|
72
|
-
router.post('/:projectSlug/setup-bmad',
|
|
17
|
+
router.post('/:projectSlug/setup-bmad', projectController.setupBmad);
|
|
73
18
|
// DELETE /api/projects/:projectSlug - Delete a project
|
|
74
19
|
router.delete('/:projectSlug', projectController.delete);
|
|
75
20
|
// GET /api/projects/:projectSlug/settings - Get project settings with effective values
|
|
@@ -80,7 +25,7 @@ router.patch('/:projectSlug/settings', projectController.updateSettings);
|
|
|
80
25
|
router.get('/:projectSlug/system-prompt', projectController.getSystemPrompt);
|
|
81
26
|
// POST /api/projects/:projectSlug/open-explorer - Open project in system file explorer (localhost only)
|
|
82
27
|
router.post('/:projectSlug/open-explorer', projectController.openExplorer);
|
|
83
|
-
// POST /api/projects/validate-path - Validate directory path
|
|
84
|
-
router.post('/validate-path',
|
|
28
|
+
// POST /api/projects/validate-path - Validate directory path
|
|
29
|
+
router.post('/validate-path', projectController.validatePath);
|
|
85
30
|
export default router;
|
|
86
31
|
//# sourceMappingURL=projects.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"projects.js","sourceRoot":"","sources":["../../src/routes/projects.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"projects.js","sourceRoot":"","sources":["../../src/routes/projects.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAExE,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;AAExB,wCAAwC;AACxC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,iBAAiB,CAAC,IAAI,CAAC,CAAC;AAExC,0CAA0C;AAC1C,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC;AAE3C,wEAAwE;AACxE,MAAM,CAAC,GAAG,CAAC,gBAAgB,EAAE,iBAAiB,CAAC,YAAY,CAAC,CAAC;AAE7D,+EAA+E;AAC/E,MAAM,CAAC,IAAI,CAAC,0BAA0B,EAAE,iBAAiB,CAAC,SAAS,CAAC,CAAC;AAErE,uDAAuD;AACvD,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC;AAEzD,uFAAuF;AACvF,MAAM,CAAC,GAAG,CAAC,wBAAwB,EAAE,iBAAiB,CAAC,WAAW,CAAC,CAAC;AAEpE,sEAAsE;AACtE,MAAM,CAAC,KAAK,CAAC,wBAAwB,EAAE,iBAAiB,CAAC,cAAc,CAAC,CAAC;AAEzE,2EAA2E;AAC3E,MAAM,CAAC,GAAG,CAAC,6BAA6B,EAAE,iBAAiB,CAAC,eAAe,CAAC,CAAC;AAE7E,wGAAwG;AACxG,MAAM,CAAC,IAAI,CAAC,6BAA6B,EAAE,iBAAiB,CAAC,YAAY,CAAC,CAAC;AAE3E,6DAA6D;AAC7D,MAAM,CAAC,IAAI,CAAC,gBAAgB,EAAE,iBAAiB,CAAC,YAAY,CAAC,CAAC;AAE9D,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Story 29.2: Snippet management routes.
|
|
3
|
+
*
|
|
4
|
+
* Mounted at `/api/snippets`. Intentionally distinct from `/api/harness/*`
|
|
5
|
+
* because snippets are Hammoc-native (`%name%` chat-input expansion via
|
|
6
|
+
* `snippetResolver`), not a Claude Code harness primitive — keeping the
|
|
7
|
+
* namespaces separate makes the system-of-record obvious at the URL boundary.
|
|
8
|
+
*
|
|
9
|
+
* Route ordering: literal segments (`/copy`) live above the dynamic
|
|
10
|
+
* `/:scope/:name` so Express prefers them.
|
|
11
|
+
*/
|
|
12
|
+
declare const router: import("express-serve-static-core").Router;
|
|
13
|
+
export default router;
|
|
14
|
+
//# sourceMappingURL=snippets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snippets.d.ts","sourceRoot":"","sources":["../../src/routes/snippets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH,QAAA,MAAM,MAAM,4CAAW,CAAC;AAgBxB,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Story 29.2: Snippet management routes.
|
|
3
|
+
*
|
|
4
|
+
* Mounted at `/api/snippets`. Intentionally distinct from `/api/harness/*`
|
|
5
|
+
* because snippets are Hammoc-native (`%name%` chat-input expansion via
|
|
6
|
+
* `snippetResolver`), not a Claude Code harness primitive — keeping the
|
|
7
|
+
* namespaces separate makes the system-of-record obvious at the URL boundary.
|
|
8
|
+
*
|
|
9
|
+
* Route ordering: literal segments (`/copy`) live above the dynamic
|
|
10
|
+
* `/:scope/:name` so Express prefers them.
|
|
11
|
+
*/
|
|
12
|
+
import { Router } from 'express';
|
|
13
|
+
import express from 'express';
|
|
14
|
+
import { snippetController } from '../controllers/snippetController.js';
|
|
15
|
+
const router = Router();
|
|
16
|
+
const largeBodyParser = express.json({ limit: '5mb' });
|
|
17
|
+
const smallBodyParser = express.json({ limit: '64kb' });
|
|
18
|
+
router.get('/', snippetController.list);
|
|
19
|
+
// Literal-segment endpoints first.
|
|
20
|
+
router.post('/copy', smallBodyParser, snippetController.copy);
|
|
21
|
+
// Dynamic `:scope/:name` endpoints.
|
|
22
|
+
router.get('/:scope/:name', snippetController.read);
|
|
23
|
+
router.post('/:scope/:name', largeBodyParser, snippetController.create);
|
|
24
|
+
router.put('/:scope/:name', largeBodyParser, snippetController.update);
|
|
25
|
+
router.delete('/:scope/:name', smallBodyParser, snippetController.delete);
|
|
26
|
+
export default router;
|
|
27
|
+
//# sourceMappingURL=snippets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snippets.js","sourceRoot":"","sources":["../../src/routes/snippets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAExE,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;AAExB,MAAM,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;AACvD,MAAM,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;AAExD,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,iBAAiB,CAAC,IAAI,CAAC,CAAC;AAExC,mCAAmC;AACnC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,EAAE,iBAAiB,CAAC,IAAI,CAAC,CAAC;AAE9D,oCAAoC;AACpC,MAAM,CAAC,GAAG,CAAC,eAAe,EAAE,iBAAiB,CAAC,IAAI,CAAC,CAAC;AACpD,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE,eAAe,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC;AACxE,MAAM,CAAC,GAAG,CAAC,eAAe,EAAE,eAAe,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC;AACvE,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,eAAe,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC;AAE1E,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Story 31.1: BMad core-config editor service (Epic 31).
|
|
3
|
+
*
|
|
4
|
+
* Domain: the single `<projectRoot>/.bmad-core/core-config.yaml` file that
|
|
5
|
+
* drives downstream BMad agents (`/dev` · `/sm` · `/qa`). This file is the
|
|
6
|
+
* SIBLING of `.claude/` (it lives under `.bmad-core/`, outside the harness
|
|
7
|
+
* whitelist), so it gets a dedicated canonical-path resolver
|
|
8
|
+
* (`resolveBmadCoreConfigPath`) exactly like Story 29.1's CLAUDE.md and Story
|
|
9
|
+
* 30.7's `.gitignore`.
|
|
10
|
+
*
|
|
11
|
+
* Separation from `bmadStatusService`: that service SCANS the whole BMad
|
|
12
|
+
* project (epics, stories, QA, documents) and returns a status snapshot;
|
|
13
|
+
* this service does single-file R/W on the config itself. They read the same
|
|
14
|
+
* file but expose different shapes (status snapshot vs raw config + AST ops),
|
|
15
|
+
* so they stay separate.
|
|
16
|
+
*
|
|
17
|
+
* YAML parser single source of truth: `yaml` (eemeli) via
|
|
18
|
+
* `structuredEditor.applyYamlPatch`, which preserves comments, key order,
|
|
19
|
+
* quoting, and blank-line metadata across a patch. `js-yaml@4` (used by
|
|
20
|
+
* `bmadStatusService` for a lossy status read) must NOT be used here — it has
|
|
21
|
+
* no comment-preservation path (see structuredEditor.ts header).
|
|
22
|
+
*
|
|
23
|
+
* Method contract (all throw typed errors from `HARNESS_ERRORS`):
|
|
24
|
+
* read — content + mtime; missing file → HARNESS_FILE_NOT_FOUND
|
|
25
|
+
* patchKey — AST patch preserving comments/order; STALE_WRITE guard
|
|
26
|
+
* writeRaw — raw text overwrite (Raw editor); same STALE_WRITE guard
|
|
27
|
+
* parseUnknownKeys — partition parsed YAML into known/unknown top-level keys
|
|
28
|
+
*/
|
|
29
|
+
import { type HarnessStructuredPatchOp, type BmadCoreConfigKnownKeys } from '@hammoc/shared';
|
|
30
|
+
export interface BmadCoreConfigReadResult {
|
|
31
|
+
content: string;
|
|
32
|
+
mtime: string;
|
|
33
|
+
}
|
|
34
|
+
export interface BmadCoreConfigParsed {
|
|
35
|
+
knownKeys: BmadCoreConfigKnownKeys;
|
|
36
|
+
unknownKeys: Record<string, unknown>;
|
|
37
|
+
}
|
|
38
|
+
declare class BmadCoreConfigService {
|
|
39
|
+
/**
|
|
40
|
+
* Read the raw config text + mtime. Missing file →
|
|
41
|
+
* HARNESS_FILE_NOT_FOUND: the BMad-project gate means this service is only
|
|
42
|
+
* ever called for projects that have `.bmad-core/`, so a missing
|
|
43
|
+
* core-config.yaml is an abnormal state, not an empty-state.
|
|
44
|
+
*/
|
|
45
|
+
read(projectSlug: string): Promise<BmadCoreConfigReadResult>;
|
|
46
|
+
/**
|
|
47
|
+
* Partition a parsed config into the 10 known top-level keys vs everything
|
|
48
|
+
* else. Known nested groups (`qa`/`prd`/`architecture`/`brownfieldEpic`)
|
|
49
|
+
* pass through whole; their leaves are the 18-key matrix the form renders.
|
|
50
|
+
* Unknown top-level keys are surfaced read-only (AC4). Unparseable input →
|
|
51
|
+
* HARNESS_PARSE_ERROR so the client can fall back to raw editing.
|
|
52
|
+
*/
|
|
53
|
+
parseUnknownKeys(content: string): BmadCoreConfigParsed;
|
|
54
|
+
/**
|
|
55
|
+
* Apply AST-level patches to the config, preserving comments/order/quoting
|
|
56
|
+
* for every untouched node — including unknown keys (AC4.b). Running through
|
|
57
|
+
* a read → patch → write round trip means an external mutation that slipped
|
|
58
|
+
* in between read and write surfaces as STALE_WRITE.
|
|
59
|
+
*
|
|
60
|
+
* `expectedMtime` semantics mirror `harnessService.patchStructured`: when the
|
|
61
|
+
* client supplies it, that value is the guard; otherwise the freshly-read
|
|
62
|
+
* mtime guards against a concurrent write during our own round trip.
|
|
63
|
+
*/
|
|
64
|
+
patchKey(projectSlug: string, ops: HarnessStructuredPatchOp[], expectedMtime?: string): Promise<{
|
|
65
|
+
mtime: string;
|
|
66
|
+
}>;
|
|
67
|
+
/**
|
|
68
|
+
* Raw-mode overwrite: write the supplied text verbatim, bypassing the AST
|
|
69
|
+
* patch (the user intentionally took control of the whole file). The
|
|
70
|
+
* STALE_WRITE guard still applies so a raw save cannot silently clobber an
|
|
71
|
+
* external edit (AC5.b).
|
|
72
|
+
*/
|
|
73
|
+
writeRaw(projectSlug: string, content: string, expectedMtime?: string): Promise<{
|
|
74
|
+
mtime: string;
|
|
75
|
+
}>;
|
|
76
|
+
/**
|
|
77
|
+
* Shared write tail: STALE_WRITE guard + writeFile + self-write echo
|
|
78
|
+
* suppression. Mirrors `harnessService.write` / `claudeMdService.write`.
|
|
79
|
+
* The parent `.bmad-core/` directory is guaranteed to exist (BMad-project
|
|
80
|
+
* gate), so there is no auto-mkdir path here.
|
|
81
|
+
*/
|
|
82
|
+
private writeInternal;
|
|
83
|
+
}
|
|
84
|
+
export declare const bmadCoreConfigService: BmadCoreConfigService;
|
|
85
|
+
export {};
|
|
86
|
+
//# sourceMappingURL=bmadCoreConfigService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bmadCoreConfigService.d.ts","sourceRoot":"","sources":["../../src/services/bmadCoreConfigService.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAIH,OAAO,EAGL,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,EAC7B,MAAM,gBAAgB,CAAC;AAcxB,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,uBAAuB,CAAC;IACnC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,cAAM,qBAAqB;IACzB;;;;;OAKG;IACG,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAyBlE;;;;;;OAMG;IACH,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,oBAAoB;IA4BvD;;;;;;;;;OASG;IACG,QAAQ,CACZ,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,wBAAwB,EAAE,EAC/B,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAS7B;;;;;OAKG;IACG,QAAQ,CACZ,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAK7B;;;;;OAKG;YACW,aAAa;CA0C5B;AAED,eAAO,MAAM,qBAAqB,uBAA8B,CAAC"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Story 31.1: BMad core-config editor service (Epic 31).
|
|
3
|
+
*
|
|
4
|
+
* Domain: the single `<projectRoot>/.bmad-core/core-config.yaml` file that
|
|
5
|
+
* drives downstream BMad agents (`/dev` · `/sm` · `/qa`). This file is the
|
|
6
|
+
* SIBLING of `.claude/` (it lives under `.bmad-core/`, outside the harness
|
|
7
|
+
* whitelist), so it gets a dedicated canonical-path resolver
|
|
8
|
+
* (`resolveBmadCoreConfigPath`) exactly like Story 29.1's CLAUDE.md and Story
|
|
9
|
+
* 30.7's `.gitignore`.
|
|
10
|
+
*
|
|
11
|
+
* Separation from `bmadStatusService`: that service SCANS the whole BMad
|
|
12
|
+
* project (epics, stories, QA, documents) and returns a status snapshot;
|
|
13
|
+
* this service does single-file R/W on the config itself. They read the same
|
|
14
|
+
* file but expose different shapes (status snapshot vs raw config + AST ops),
|
|
15
|
+
* so they stay separate.
|
|
16
|
+
*
|
|
17
|
+
* YAML parser single source of truth: `yaml` (eemeli) via
|
|
18
|
+
* `structuredEditor.applyYamlPatch`, which preserves comments, key order,
|
|
19
|
+
* quoting, and blank-line metadata across a patch. `js-yaml@4` (used by
|
|
20
|
+
* `bmadStatusService` for a lossy status read) must NOT be used here — it has
|
|
21
|
+
* no comment-preservation path (see structuredEditor.ts header).
|
|
22
|
+
*
|
|
23
|
+
* Method contract (all throw typed errors from `HARNESS_ERRORS`):
|
|
24
|
+
* read — content + mtime; missing file → HARNESS_FILE_NOT_FOUND
|
|
25
|
+
* patchKey — AST patch preserving comments/order; STALE_WRITE guard
|
|
26
|
+
* writeRaw — raw text overwrite (Raw editor); same STALE_WRITE guard
|
|
27
|
+
* parseUnknownKeys — partition parsed YAML into known/unknown top-level keys
|
|
28
|
+
*/
|
|
29
|
+
import fs from 'fs/promises';
|
|
30
|
+
import { parse as parseYaml } from 'yaml';
|
|
31
|
+
import { HARNESS_ERRORS, BMAD_CORE_CONFIG_KNOWN_TOP_LEVEL_KEYS, } from '@hammoc/shared';
|
|
32
|
+
import { resolveBmadCoreConfigPath } from '../utils/harnessPaths.js';
|
|
33
|
+
import { applyYamlPatch } from '../utils/structuredEditor.js';
|
|
34
|
+
import { fileWatcherService } from './fileWatcherService.js';
|
|
35
|
+
function throwMapped(code, message, extras) {
|
|
36
|
+
const err = new Error(message);
|
|
37
|
+
err.code = code;
|
|
38
|
+
if (extras)
|
|
39
|
+
Object.assign(err, extras);
|
|
40
|
+
throw err;
|
|
41
|
+
}
|
|
42
|
+
const KNOWN_TOP_LEVEL = new Set(BMAD_CORE_CONFIG_KNOWN_TOP_LEVEL_KEYS);
|
|
43
|
+
class BmadCoreConfigService {
|
|
44
|
+
/**
|
|
45
|
+
* Read the raw config text + mtime. Missing file →
|
|
46
|
+
* HARNESS_FILE_NOT_FOUND: the BMad-project gate means this service is only
|
|
47
|
+
* ever called for projects that have `.bmad-core/`, so a missing
|
|
48
|
+
* core-config.yaml is an abnormal state, not an empty-state.
|
|
49
|
+
*/
|
|
50
|
+
async read(projectSlug) {
|
|
51
|
+
const { absolutePath } = await resolveBmadCoreConfigPath(projectSlug);
|
|
52
|
+
let stat;
|
|
53
|
+
try {
|
|
54
|
+
stat = await fs.stat(absolutePath);
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
const code = error.code;
|
|
58
|
+
if (code === 'ENOENT') {
|
|
59
|
+
throwMapped(HARNESS_ERRORS.HARNESS_FILE_NOT_FOUND.code, 'core-config.yaml not found', { absolutePath });
|
|
60
|
+
}
|
|
61
|
+
if (code === 'EACCES') {
|
|
62
|
+
throwMapped(HARNESS_ERRORS.HARNESS_FORBIDDEN.code, 'permission denied');
|
|
63
|
+
}
|
|
64
|
+
throw error;
|
|
65
|
+
}
|
|
66
|
+
if (!stat.isFile()) {
|
|
67
|
+
throwMapped(HARNESS_ERRORS.HARNESS_NOT_A_FILE.code, 'path is not a file');
|
|
68
|
+
}
|
|
69
|
+
const content = await fs.readFile(absolutePath, 'utf-8');
|
|
70
|
+
return { content, mtime: stat.mtime.toISOString() };
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Partition a parsed config into the 10 known top-level keys vs everything
|
|
74
|
+
* else. Known nested groups (`qa`/`prd`/`architecture`/`brownfieldEpic`)
|
|
75
|
+
* pass through whole; their leaves are the 18-key matrix the form renders.
|
|
76
|
+
* Unknown top-level keys are surfaced read-only (AC4). Unparseable input →
|
|
77
|
+
* HARNESS_PARSE_ERROR so the client can fall back to raw editing.
|
|
78
|
+
*/
|
|
79
|
+
parseUnknownKeys(content) {
|
|
80
|
+
let parsed;
|
|
81
|
+
try {
|
|
82
|
+
parsed = parseYaml(content);
|
|
83
|
+
}
|
|
84
|
+
catch (cause) {
|
|
85
|
+
throwMapped(HARNESS_ERRORS.HARNESS_PARSE_ERROR.code, `failed to parse core-config.yaml: ${cause?.message ?? String(cause)}`);
|
|
86
|
+
}
|
|
87
|
+
const knownKeys = {};
|
|
88
|
+
const unknownKeys = {};
|
|
89
|
+
// A comment-only / empty file parses to null or a scalar — treat as no keys.
|
|
90
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
91
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
92
|
+
if (KNOWN_TOP_LEVEL.has(key)) {
|
|
93
|
+
knownKeys[key] = value;
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
unknownKeys[key] = value;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return { knownKeys: knownKeys, unknownKeys };
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Apply AST-level patches to the config, preserving comments/order/quoting
|
|
104
|
+
* for every untouched node — including unknown keys (AC4.b). Running through
|
|
105
|
+
* a read → patch → write round trip means an external mutation that slipped
|
|
106
|
+
* in between read and write surfaces as STALE_WRITE.
|
|
107
|
+
*
|
|
108
|
+
* `expectedMtime` semantics mirror `harnessService.patchStructured`: when the
|
|
109
|
+
* client supplies it, that value is the guard; otherwise the freshly-read
|
|
110
|
+
* mtime guards against a concurrent write during our own round trip.
|
|
111
|
+
*/
|
|
112
|
+
async patchKey(projectSlug, ops, expectedMtime) {
|
|
113
|
+
const { absolutePath } = await resolveBmadCoreConfigPath(projectSlug);
|
|
114
|
+
const current = await this.read(projectSlug);
|
|
115
|
+
const patched = applyYamlPatch(current.content, ops);
|
|
116
|
+
const guardMtime = expectedMtime ?? current.mtime;
|
|
117
|
+
return this.writeInternal(absolutePath, patched, guardMtime);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Raw-mode overwrite: write the supplied text verbatim, bypassing the AST
|
|
121
|
+
* patch (the user intentionally took control of the whole file). The
|
|
122
|
+
* STALE_WRITE guard still applies so a raw save cannot silently clobber an
|
|
123
|
+
* external edit (AC5.b).
|
|
124
|
+
*/
|
|
125
|
+
async writeRaw(projectSlug, content, expectedMtime) {
|
|
126
|
+
const { absolutePath } = await resolveBmadCoreConfigPath(projectSlug);
|
|
127
|
+
return this.writeInternal(absolutePath, content, expectedMtime);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Shared write tail: STALE_WRITE guard + writeFile + self-write echo
|
|
131
|
+
* suppression. Mirrors `harnessService.write` / `claudeMdService.write`.
|
|
132
|
+
* The parent `.bmad-core/` directory is guaranteed to exist (BMad-project
|
|
133
|
+
* gate), so there is no auto-mkdir path here.
|
|
134
|
+
*/
|
|
135
|
+
async writeInternal(absolutePath, content, expectedMtime) {
|
|
136
|
+
if (expectedMtime !== undefined) {
|
|
137
|
+
try {
|
|
138
|
+
const existing = await fs.stat(absolutePath);
|
|
139
|
+
const currentMtime = existing.mtime.toISOString();
|
|
140
|
+
if (currentMtime !== expectedMtime) {
|
|
141
|
+
throwMapped(HARNESS_ERRORS.HARNESS_STALE_WRITE.code, 'file changed on disk', { currentMtime });
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
const code = error.code;
|
|
146
|
+
if (code === 'ENOENT') {
|
|
147
|
+
throwMapped(HARNESS_ERRORS.HARNESS_STALE_WRITE.code, 'file missing on disk', { currentMtime: '' });
|
|
148
|
+
}
|
|
149
|
+
if (code === HARNESS_ERRORS.HARNESS_STALE_WRITE.code)
|
|
150
|
+
throw error;
|
|
151
|
+
if (code === 'EACCES') {
|
|
152
|
+
throwMapped(HARNESS_ERRORS.HARNESS_FORBIDDEN.code, 'permission denied');
|
|
153
|
+
}
|
|
154
|
+
// Any other stat failure: fall through and let writeFile surface it.
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
try {
|
|
158
|
+
await fs.writeFile(absolutePath, content, 'utf-8');
|
|
159
|
+
}
|
|
160
|
+
catch (error) {
|
|
161
|
+
const code = error.code;
|
|
162
|
+
if (code === 'EACCES') {
|
|
163
|
+
throwMapped(HARNESS_ERRORS.HARNESS_FORBIDDEN.code, 'permission denied');
|
|
164
|
+
}
|
|
165
|
+
throwMapped(HARNESS_ERRORS.HARNESS_WRITE_ERROR.code, 'failed to write file');
|
|
166
|
+
}
|
|
167
|
+
const stat = await fs.stat(absolutePath);
|
|
168
|
+
// Share the harness self-write suppression map so the `.bmad-core/`
|
|
169
|
+
// watcher (Task A.4) swallows our own-write echo on the same path.
|
|
170
|
+
fileWatcherService.noteLocalWrite(absolutePath);
|
|
171
|
+
return { mtime: stat.mtime.toISOString() };
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
export const bmadCoreConfigService = new BmadCoreConfigService();
|
|
175
|
+
//# sourceMappingURL=bmadCoreConfigService.js.map
|