@specforge/cli 0.1.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 +781 -0
- package/bin/specforge +21 -0
- package/dist/channel.d.ts +27 -0
- package/dist/channel.d.ts.map +1 -0
- package/dist/channel.js +22 -0
- package/dist/channel.js.map +1 -0
- package/dist/cli/commands/configure.d.ts +16 -0
- package/dist/cli/commands/configure.d.ts.map +1 -0
- package/dist/cli/commands/configure.js +186 -0
- package/dist/cli/commands/configure.js.map +1 -0
- package/dist/cli/commands/configure.types.d.ts +110 -0
- package/dist/cli/commands/configure.types.d.ts.map +1 -0
- package/dist/cli/commands/configure.types.js +82 -0
- package/dist/cli/commands/configure.types.js.map +1 -0
- package/dist/cli/commands/debug/call.d.ts +14 -0
- package/dist/cli/commands/debug/call.d.ts.map +1 -0
- package/dist/cli/commands/debug/call.js +96 -0
- package/dist/cli/commands/debug/call.js.map +1 -0
- package/dist/cli/commands/debug/index.d.ts +12 -0
- package/dist/cli/commands/debug/index.d.ts.map +1 -0
- package/dist/cli/commands/debug/index.js +14 -0
- package/dist/cli/commands/debug/index.js.map +1 -0
- package/dist/cli/commands/debug/register.d.ts +11 -0
- package/dist/cli/commands/debug/register.d.ts.map +1 -0
- package/dist/cli/commands/debug/register.js +78 -0
- package/dist/cli/commands/debug/register.js.map +1 -0
- package/dist/cli/commands/debug/test.d.ts +13 -0
- package/dist/cli/commands/debug/test.d.ts.map +1 -0
- package/dist/cli/commands/debug/test.js +91 -0
- package/dist/cli/commands/debug/test.js.map +1 -0
- package/dist/cli/commands/debug/tools.d.ts +13 -0
- package/dist/cli/commands/debug/tools.d.ts.map +1 -0
- package/dist/cli/commands/debug/tools.js +86 -0
- package/dist/cli/commands/debug/tools.js.map +1 -0
- package/dist/cli/commands/debug/types.d.ts +119 -0
- package/dist/cli/commands/debug/types.d.ts.map +1 -0
- package/dist/cli/commands/debug/types.js +36 -0
- package/dist/cli/commands/debug/types.js.map +1 -0
- package/dist/cli/commands/debug/whoami.d.ts +13 -0
- package/dist/cli/commands/debug/whoami.d.ts.map +1 -0
- package/dist/cli/commands/debug/whoami.js +131 -0
- package/dist/cli/commands/debug/whoami.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +16 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +413 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/doctor.types.d.ts +180 -0
- package/dist/cli/commands/doctor.types.d.ts.map +1 -0
- package/dist/cli/commands/doctor.types.js +140 -0
- package/dist/cli/commands/doctor.types.js.map +1 -0
- package/dist/cli/commands/feedback.d.ts +27 -0
- package/dist/cli/commands/feedback.d.ts.map +1 -0
- package/dist/cli/commands/feedback.js +262 -0
- package/dist/cli/commands/feedback.js.map +1 -0
- package/dist/cli/commands/feedback.types.d.ts +116 -0
- package/dist/cli/commands/feedback.types.d.ts.map +1 -0
- package/dist/cli/commands/feedback.types.js +65 -0
- package/dist/cli/commands/feedback.types.js.map +1 -0
- package/dist/cli/commands/index.d.ts +15 -0
- package/dist/cli/commands/index.d.ts.map +1 -0
- package/dist/cli/commands/index.js +21 -0
- package/dist/cli/commands/index.js.map +1 -0
- package/dist/cli/commands/init.d.ts +17 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +773 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/init.types.d.ts +193 -0
- package/dist/cli/commands/init.types.d.ts.map +1 -0
- package/dist/cli/commands/init.types.js +29 -0
- package/dist/cli/commands/init.types.js.map +1 -0
- package/dist/cli/commands/invitations.d.ts +31 -0
- package/dist/cli/commands/invitations.d.ts.map +1 -0
- package/dist/cli/commands/invitations.js +250 -0
- package/dist/cli/commands/invitations.js.map +1 -0
- package/dist/cli/commands/login.d.ts +40 -0
- package/dist/cli/commands/login.d.ts.map +1 -0
- package/dist/cli/commands/login.js +139 -0
- package/dist/cli/commands/login.js.map +1 -0
- package/dist/cli/commands/members.d.ts +55 -0
- package/dist/cli/commands/members.d.ts.map +1 -0
- package/dist/cli/commands/members.js +296 -0
- package/dist/cli/commands/members.js.map +1 -0
- package/dist/cli/commands/scaffold/agent-types.d.ts +54 -0
- package/dist/cli/commands/scaffold/agent-types.d.ts.map +1 -0
- package/dist/cli/commands/scaffold/agent-types.js +22 -0
- package/dist/cli/commands/scaffold/agent-types.js.map +1 -0
- package/dist/cli/commands/scaffold/display.d.ts +56 -0
- package/dist/cli/commands/scaffold/display.d.ts.map +1 -0
- package/dist/cli/commands/scaffold/display.js +217 -0
- package/dist/cli/commands/scaffold/display.js.map +1 -0
- package/dist/cli/commands/scaffold/files.d.ts +99 -0
- package/dist/cli/commands/scaffold/files.d.ts.map +1 -0
- package/dist/cli/commands/scaffold/files.js +122 -0
- package/dist/cli/commands/scaffold/files.js.map +1 -0
- package/dist/cli/commands/scaffold/index.d.ts +13 -0
- package/dist/cli/commands/scaffold/index.d.ts.map +1 -0
- package/dist/cli/commands/scaffold/index.js +12 -0
- package/dist/cli/commands/scaffold/index.js.map +1 -0
- package/dist/cli/commands/scaffold/register.d.ts +11 -0
- package/dist/cli/commands/scaffold/register.d.ts.map +1 -0
- package/dist/cli/commands/scaffold/register.js +11 -0
- package/dist/cli/commands/scaffold/register.js.map +1 -0
- package/dist/cli/commands/scaffold/scaffold.d.ts +11 -0
- package/dist/cli/commands/scaffold/scaffold.d.ts.map +1 -0
- package/dist/cli/commands/scaffold/scaffold.js +728 -0
- package/dist/cli/commands/scaffold/scaffold.js.map +1 -0
- package/dist/cli/commands/scaffold/targets.d.ts +60 -0
- package/dist/cli/commands/scaffold/targets.d.ts.map +1 -0
- package/dist/cli/commands/scaffold/targets.js +251 -0
- package/dist/cli/commands/scaffold/targets.js.map +1 -0
- package/dist/cli/commands/scaffold/types.d.ts +170 -0
- package/dist/cli/commands/scaffold/types.d.ts.map +1 -0
- package/dist/cli/commands/scaffold/types.js +12 -0
- package/dist/cli/commands/scaffold/types.js.map +1 -0
- package/dist/cli/commands/scaffold/utils.d.ts +89 -0
- package/dist/cli/commands/scaffold/utils.d.ts.map +1 -0
- package/dist/cli/commands/scaffold/utils.js +401 -0
- package/dist/cli/commands/scaffold/utils.js.map +1 -0
- package/dist/cli/commands/status.d.ts +19 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +124 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/status.types.d.ts +37 -0
- package/dist/cli/commands/status.types.d.ts.map +1 -0
- package/dist/cli/commands/status.types.js +7 -0
- package/dist/cli/commands/status.types.js.map +1 -0
- package/dist/cli/commands/switch.d.ts +18 -0
- package/dist/cli/commands/switch.d.ts.map +1 -0
- package/dist/cli/commands/switch.js +134 -0
- package/dist/cli/commands/switch.js.map +1 -0
- package/dist/cli/commands/switch.types.d.ts +123 -0
- package/dist/cli/commands/switch.types.d.ts.map +1 -0
- package/dist/cli/commands/switch.types.js +46 -0
- package/dist/cli/commands/switch.types.js.map +1 -0
- package/dist/cli/config/agent-teams.types.d.ts +120 -0
- package/dist/cli/config/agent-teams.types.d.ts.map +1 -0
- package/dist/cli/config/agent-teams.types.js +23 -0
- package/dist/cli/config/agent-teams.types.js.map +1 -0
- package/dist/cli/config/index.d.ts +13 -0
- package/dist/cli/config/index.d.ts.map +1 -0
- package/dist/cli/config/index.js +7 -0
- package/dist/cli/config/index.js.map +1 -0
- package/dist/cli/config/loader.d.ts +114 -0
- package/dist/cli/config/loader.d.ts.map +1 -0
- package/dist/cli/config/loader.js +198 -0
- package/dist/cli/config/loader.js.map +1 -0
- package/dist/cli/config/paths.d.ts +107 -0
- package/dist/cli/config/paths.d.ts.map +1 -0
- package/dist/cli/config/paths.js +79 -0
- package/dist/cli/config/paths.js.map +1 -0
- package/dist/cli/config/planning-sessions-registry.d.ts +52 -0
- package/dist/cli/config/planning-sessions-registry.d.ts.map +1 -0
- package/dist/cli/config/planning-sessions-registry.js +46 -0
- package/dist/cli/config/planning-sessions-registry.js.map +1 -0
- package/dist/cli/config/types.d.ts +186 -0
- package/dist/cli/config/types.d.ts.map +1 -0
- package/dist/cli/config/types.js +27 -0
- package/dist/cli/config/types.js.map +1 -0
- package/dist/cli/config/validation.d.ts +62 -0
- package/dist/cli/config/validation.d.ts.map +1 -0
- package/dist/cli/config/validation.js +133 -0
- package/dist/cli/config/validation.js.map +1 -0
- package/dist/cli/config/writer.d.ts +153 -0
- package/dist/cli/config/writer.d.ts.map +1 -0
- package/dist/cli/config/writer.js +168 -0
- package/dist/cli/config/writer.js.map +1 -0
- package/dist/cli/index.d.ts +30 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +142 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/middleware/auth-guard.d.ts +107 -0
- package/dist/cli/middleware/auth-guard.d.ts.map +1 -0
- package/dist/cli/middleware/auth-guard.js +97 -0
- package/dist/cli/middleware/auth-guard.js.map +1 -0
- package/dist/cli/middleware/error-handler.d.ts +133 -0
- package/dist/cli/middleware/error-handler.d.ts.map +1 -0
- package/dist/cli/middleware/error-handler.js +139 -0
- package/dist/cli/middleware/error-handler.js.map +1 -0
- package/dist/cli/middleware/index.d.ts +6 -0
- package/dist/cli/middleware/index.d.ts.map +1 -0
- package/dist/cli/middleware/index.js +3 -0
- package/dist/cli/middleware/index.js.map +1 -0
- package/dist/cli/templates/agents/content/core/sfag-orchestrator.d.ts +9 -0
- package/dist/cli/templates/agents/content/core/sfag-orchestrator.d.ts.map +1 -0
- package/dist/cli/templates/agents/content/core/sfag-orchestrator.js +160 -0
- package/dist/cli/templates/agents/content/core/sfag-orchestrator.js.map +1 -0
- package/dist/cli/templates/agents/content/core/sfag-spec-creator.d.ts +9 -0
- package/dist/cli/templates/agents/content/core/sfag-spec-creator.d.ts.map +1 -0
- package/dist/cli/templates/agents/content/core/sfag-spec-creator.js +343 -0
- package/dist/cli/templates/agents/content/core/sfag-spec-creator.js.map +1 -0
- package/dist/cli/templates/agents/content/core/sfag-ticket-implementer.d.ts +9 -0
- package/dist/cli/templates/agents/content/core/sfag-ticket-implementer.d.ts.map +1 -0
- package/dist/cli/templates/agents/content/core/sfag-ticket-implementer.js +254 -0
- package/dist/cli/templates/agents/content/core/sfag-ticket-implementer.js.map +1 -0
- package/dist/cli/templates/agents/content/research/sfag-package-researcher.d.ts +8 -0
- package/dist/cli/templates/agents/content/research/sfag-package-researcher.d.ts.map +1 -0
- package/dist/cli/templates/agents/content/research/sfag-package-researcher.js +128 -0
- package/dist/cli/templates/agents/content/research/sfag-package-researcher.js.map +1 -0
- package/dist/cli/templates/agents/index.d.ts +23 -0
- package/dist/cli/templates/agents/index.d.ts.map +1 -0
- package/dist/cli/templates/agents/index.js +29 -0
- package/dist/cli/templates/agents/index.js.map +1 -0
- package/dist/cli/templates/commands.d.ts +17 -0
- package/dist/cli/templates/commands.d.ts.map +1 -0
- package/dist/cli/templates/commands.js +78 -0
- package/dist/cli/templates/commands.js.map +1 -0
- package/dist/cli/templates/content/sf-blockers.d.ts +7 -0
- package/dist/cli/templates/content/sf-blockers.d.ts.map +1 -0
- package/dist/cli/templates/content/sf-blockers.js +69 -0
- package/dist/cli/templates/content/sf-blockers.js.map +1 -0
- package/dist/cli/templates/content/sf-commit.d.ts +7 -0
- package/dist/cli/templates/content/sf-commit.d.ts.map +1 -0
- package/dist/cli/templates/content/sf-commit.js +79 -0
- package/dist/cli/templates/content/sf-commit.js.map +1 -0
- package/dist/cli/templates/content/sf-context.d.ts +7 -0
- package/dist/cli/templates/content/sf-context.d.ts.map +1 -0
- package/dist/cli/templates/content/sf-context.js +63 -0
- package/dist/cli/templates/content/sf-context.js.map +1 -0
- package/dist/cli/templates/content/sf-help.d.ts +7 -0
- package/dist/cli/templates/content/sf-help.d.ts.map +1 -0
- package/dist/cli/templates/content/sf-help.js +42 -0
- package/dist/cli/templates/content/sf-help.js.map +1 -0
- package/dist/cli/templates/content/sf-init.d.ts +7 -0
- package/dist/cli/templates/content/sf-init.d.ts.map +1 -0
- package/dist/cli/templates/content/sf-init.js +62 -0
- package/dist/cli/templates/content/sf-init.js.map +1 -0
- package/dist/cli/templates/content/sf-reset.d.ts +7 -0
- package/dist/cli/templates/content/sf-reset.d.ts.map +1 -0
- package/dist/cli/templates/content/sf-reset.js +67 -0
- package/dist/cli/templates/content/sf-reset.js.map +1 -0
- package/dist/cli/templates/content/sf-search.d.ts +7 -0
- package/dist/cli/templates/content/sf-search.d.ts.map +1 -0
- package/dist/cli/templates/content/sf-search.js +63 -0
- package/dist/cli/templates/content/sf-search.js.map +1 -0
- package/dist/cli/templates/content/sf-status.d.ts +7 -0
- package/dist/cli/templates/content/sf-status.d.ts.map +1 -0
- package/dist/cli/templates/content/sf-status.js +62 -0
- package/dist/cli/templates/content/sf-status.js.map +1 -0
- package/dist/cli/templates/index.d.ts +8 -0
- package/dist/cli/templates/index.d.ts.map +1 -0
- package/dist/cli/templates/index.js +17 -0
- package/dist/cli/templates/index.js.map +1 -0
- package/dist/cli/ui/banner.d.ts +38 -0
- package/dist/cli/ui/banner.d.ts.map +1 -0
- package/dist/cli/ui/banner.js +89 -0
- package/dist/cli/ui/banner.js.map +1 -0
- package/dist/cli/ui/colors.d.ts +76 -0
- package/dist/cli/ui/colors.d.ts.map +1 -0
- package/dist/cli/ui/colors.js +67 -0
- package/dist/cli/ui/colors.js.map +1 -0
- package/dist/cli/ui/index.d.ts +7 -0
- package/dist/cli/ui/index.d.ts.map +1 -0
- package/dist/cli/ui/index.js +4 -0
- package/dist/cli/ui/index.js.map +1 -0
- package/dist/cli/ui/output.d.ts +117 -0
- package/dist/cli/ui/output.d.ts.map +1 -0
- package/dist/cli/ui/output.js +83 -0
- package/dist/cli/ui/output.js.map +1 -0
- package/dist/cli/ui/spinner.d.ts +120 -0
- package/dist/cli/ui/spinner.d.ts.map +1 -0
- package/dist/cli/ui/spinner.js +158 -0
- package/dist/cli/ui/spinner.js.map +1 -0
- package/dist/cli/ui/time.d.ts +54 -0
- package/dist/cli/ui/time.d.ts.map +1 -0
- package/dist/cli/ui/time.js +119 -0
- package/dist/cli/ui/time.js.map +1 -0
- package/dist/client/api-client.d.ts +123 -0
- package/dist/client/api-client.d.ts.map +1 -0
- package/dist/client/api-client.js +105 -0
- package/dist/client/api-client.js.map +1 -0
- package/dist/client/cli-client.d.ts +26 -0
- package/dist/client/cli-client.d.ts.map +1 -0
- package/dist/client/cli-client.js +20 -0
- package/dist/client/cli-client.js.map +1 -0
- package/dist/config/index.d.ts +78 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +79 -0
- package/dist/config/index.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +73 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/format.d.ts +126 -0
- package/dist/lib/format.d.ts.map +1 -0
- package/dist/lib/format.js +71 -0
- package/dist/lib/format.js.map +1 -0
- package/dist/lib/index.d.ts +11 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +45 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/monorepo-detector.d.ts +31 -0
- package/dist/lib/monorepo-detector.d.ts.map +1 -0
- package/dist/lib/monorepo-detector.js +188 -0
- package/dist/lib/monorepo-detector.js.map +1 -0
- package/dist/lib/prompt-generator.d.ts +65 -0
- package/dist/lib/prompt-generator.d.ts.map +1 -0
- package/dist/lib/prompt-generator.js +162 -0
- package/dist/lib/prompt-generator.js.map +1 -0
- package/dist/lib/strategy-analyzer.d.ts +59 -0
- package/dist/lib/strategy-analyzer.d.ts.map +1 -0
- package/dist/lib/strategy-analyzer.js +91 -0
- package/dist/lib/strategy-analyzer.js.map +1 -0
- package/dist/lib/workflow-definitions.d.ts +41 -0
- package/dist/lib/workflow-definitions.d.ts.map +1 -0
- package/dist/lib/workflow-definitions.js +497 -0
- package/dist/lib/workflow-definitions.js.map +1 -0
- package/dist/patterns/index.d.ts +9 -0
- package/dist/patterns/index.d.ts.map +1 -0
- package/dist/patterns/index.js +21 -0
- package/dist/patterns/index.js.map +1 -0
- package/dist/patterns/inheritance.d.ts +193 -0
- package/dist/patterns/inheritance.d.ts.map +1 -0
- package/dist/patterns/inheritance.js +125 -0
- package/dist/patterns/inheritance.js.map +1 -0
- package/dist/server.d.ts +44 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +91 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/core/context-helper.d.ts +50 -0
- package/dist/tools/core/context-helper.d.ts.map +1 -0
- package/dist/tools/core/context-helper.js +49 -0
- package/dist/tools/core/context-helper.js.map +1 -0
- package/dist/tools/core/index.d.ts +2 -0
- package/dist/tools/core/index.d.ts.map +1 -0
- package/dist/tools/core/index.js +2 -0
- package/dist/tools/core/index.js.map +1 -0
- package/dist/tools/index.d.ts +58 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +1499 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/transport/__tests__/resolve-endpoint.test.d.ts +6 -0
- package/dist/transport/__tests__/resolve-endpoint.test.d.ts.map +1 -0
- package/dist/transport/index.d.ts +6 -0
- package/dist/transport/index.d.ts.map +1 -0
- package/dist/transport/index.js +5 -0
- package/dist/transport/index.js.map +1 -0
- package/dist/transport/interface.d.ts +25 -0
- package/dist/transport/interface.d.ts.map +1 -0
- package/dist/transport/interface.js +1 -0
- package/dist/transport/interface.js.map +1 -0
- package/dist/transport/remote.d.ts +38 -0
- package/dist/transport/remote.d.ts.map +1 -0
- package/dist/transport/remote.js +107 -0
- package/dist/transport/remote.js.map +1 -0
- package/dist/transport/resolve-endpoint.d.ts +58 -0
- package/dist/transport/resolve-endpoint.d.ts.map +1 -0
- package/dist/transport/resolve-endpoint.js +146 -0
- package/dist/transport/resolve-endpoint.js.map +1 -0
- package/dist/types/index.d.ts +212 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +16 -0
- package/dist/types/index.js.map +1 -0
- package/dist/validation/index.d.ts +86 -0
- package/dist/validation/index.d.ts.map +1 -0
- package/dist/validation/index.js +392 -0
- package/dist/validation/index.js.map +1 -0
- package/dist/validation/ticket-validation.d.ts +162 -0
- package/dist/validation/ticket-validation.d.ts.map +1 -0
- package/dist/validation/ticket-validation.js +188 -0
- package/dist/validation/ticket-validation.js.map +1 -0
- package/package.json +69 -0
- package/src/cli/templates/agents/content/core/sfag-orchestrator.ts +165 -0
- package/src/cli/templates/agents/content/core/sfag-spec-creator.ts +348 -0
- package/src/cli/templates/agents/content/core/sfag-ticket-implementer.ts +259 -0
- package/src/cli/templates/agents/content/research/sfag-package-researcher.ts +132 -0
- package/src/cli/templates/agents/index.ts +47 -0
- package/src/cli/templates/commands.ts +90 -0
- package/src/cli/templates/content/sf-blockers.ts +71 -0
- package/src/cli/templates/content/sf-commit.ts +81 -0
- package/src/cli/templates/content/sf-context.ts +65 -0
- package/src/cli/templates/content/sf-help.ts +44 -0
- package/src/cli/templates/content/sf-init.ts +64 -0
- package/src/cli/templates/content/sf-reset.ts +69 -0
- package/src/cli/templates/content/sf-search.ts +65 -0
- package/src/cli/templates/content/sf-status.ts +64 -0
- package/src/cli/templates/index.ts +16 -0
- package/src/cli/templates/skills/specforge-conventions.md +114 -0
- package/src/cli/templates/skills/specforge-orchestrator.md +409 -0
- package/src/cli/templates/skills/specforge-validator.md +128 -0
- package/src/cli/templates/skills/specforge-worker.md +412 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Doctor Command Types
|
|
3
|
+
*
|
|
4
|
+
* Type definitions for the doctor command health checks.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Doctor command options from Commander
|
|
8
|
+
*/
|
|
9
|
+
export interface DoctorOptions {
|
|
10
|
+
/** Output as JSON instead of formatted text */
|
|
11
|
+
json?: boolean;
|
|
12
|
+
/** Attempt to fix issues automatically */
|
|
13
|
+
fix?: boolean;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Check status result
|
|
17
|
+
*/
|
|
18
|
+
export type CheckStatus = 'pass' | 'fail' | 'warn';
|
|
19
|
+
/**
|
|
20
|
+
* Individual check result
|
|
21
|
+
*/
|
|
22
|
+
export interface CheckResult {
|
|
23
|
+
/** Name/title of the check */
|
|
24
|
+
name: string;
|
|
25
|
+
/** Status of the check */
|
|
26
|
+
status: CheckStatus;
|
|
27
|
+
/** Detailed message about the result */
|
|
28
|
+
message: string;
|
|
29
|
+
/** Fix suggestion if check failed/warned */
|
|
30
|
+
fix?: string;
|
|
31
|
+
/** Additional metadata for JSON output */
|
|
32
|
+
metadata?: Record<string, unknown>;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Check category names
|
|
36
|
+
*/
|
|
37
|
+
export type CheckCategory = 'configuration' | 'authentication' | 'connection' | 'projectAccess';
|
|
38
|
+
/**
|
|
39
|
+
* Doctor report structure
|
|
40
|
+
*/
|
|
41
|
+
export interface DoctorReport {
|
|
42
|
+
/** Check results grouped by category */
|
|
43
|
+
checks: Record<CheckCategory, CheckResult[]>;
|
|
44
|
+
/** Summary counts */
|
|
45
|
+
summary: DoctorSummary;
|
|
46
|
+
/** Timestamp of the check */
|
|
47
|
+
timestamp: string;
|
|
48
|
+
/** Version of the CLI */
|
|
49
|
+
version?: string;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Doctor report summary
|
|
53
|
+
*/
|
|
54
|
+
export interface DoctorSummary {
|
|
55
|
+
/** Number of passed checks */
|
|
56
|
+
passed: number;
|
|
57
|
+
/** Number of failed checks */
|
|
58
|
+
failed: number;
|
|
59
|
+
/** Number of warnings */
|
|
60
|
+
warnings: number;
|
|
61
|
+
/** Total number of checks */
|
|
62
|
+
total: number;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Check category display info
|
|
66
|
+
*/
|
|
67
|
+
export interface CheckCategoryInfo {
|
|
68
|
+
/** Category identifier */
|
|
69
|
+
id: CheckCategory;
|
|
70
|
+
/** Display name */
|
|
71
|
+
name: string;
|
|
72
|
+
/** Description */
|
|
73
|
+
description: string;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Check category definitions with display info
|
|
77
|
+
*/
|
|
78
|
+
export declare const CHECK_CATEGORIES: CheckCategoryInfo[];
|
|
79
|
+
/**
|
|
80
|
+
* Check name constants for configuration checks
|
|
81
|
+
*/
|
|
82
|
+
export declare const CONFIG_CHECK_NAMES: {
|
|
83
|
+
readonly CHANNEL: "Channel";
|
|
84
|
+
readonly MCP_CONFIG_FOUND: ".mcp.json found";
|
|
85
|
+
readonly PROJECT_CONFIG_FOUND: "project config found";
|
|
86
|
+
readonly GLOBAL_CONFIG_DIR: "Global config";
|
|
87
|
+
readonly API_KEY_CONFIGURED: "API key configured";
|
|
88
|
+
readonly PLANNING_SESSION: "Active planning session";
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Check name constants for authentication checks
|
|
92
|
+
*/
|
|
93
|
+
export declare const AUTH_CHECK_NAMES: {
|
|
94
|
+
readonly API_KEY_FORMAT: "API key format valid";
|
|
95
|
+
readonly API_KEY_AUTHENTICATED: "API key authenticated";
|
|
96
|
+
readonly USER_INFO: "User info";
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* Check name constants for connection checks
|
|
100
|
+
*/
|
|
101
|
+
export declare const CONNECTION_CHECK_NAMES: {
|
|
102
|
+
readonly API_ENDPOINT_REACHABLE: "API endpoint reachable";
|
|
103
|
+
readonly RESPONSE_TIME: "Response time";
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* Check name constants for project access checks
|
|
107
|
+
*/
|
|
108
|
+
export declare const PROJECT_CHECK_NAMES: {
|
|
109
|
+
readonly PROJECT_ACCESSIBLE: "Default project accessible";
|
|
110
|
+
readonly SPECIFICATION_ACCESSIBLE: "Default specification accessible";
|
|
111
|
+
readonly IMPLEMENTATION_SESSION: "Implementation session";
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* Thresholds for performance checks
|
|
115
|
+
*/
|
|
116
|
+
export declare const PERFORMANCE_THRESHOLDS: {
|
|
117
|
+
/** Response time warning threshold in ms */
|
|
118
|
+
readonly RESPONSE_TIME_WARNING: 500;
|
|
119
|
+
/** Response time error threshold in ms */
|
|
120
|
+
readonly RESPONSE_TIME_ERROR: 5000;
|
|
121
|
+
/** Connection timeout in ms */
|
|
122
|
+
readonly CONNECTION_TIMEOUT: 10000;
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* API key validation constants
|
|
126
|
+
*/
|
|
127
|
+
export declare const API_KEY_VALIDATION: {
|
|
128
|
+
/** Required prefix for live API keys */
|
|
129
|
+
readonly PREFIX: "sf_live_";
|
|
130
|
+
/** Minimum length for valid API key */
|
|
131
|
+
readonly MIN_LENGTH: 28;
|
|
132
|
+
};
|
|
133
|
+
/**
|
|
134
|
+
* Fix suggestion templates
|
|
135
|
+
*/
|
|
136
|
+
export declare const FIX_SUGGESTIONS: {
|
|
137
|
+
readonly MISSING_MCP_CONFIG: "Run 'specforge init' to create configuration";
|
|
138
|
+
readonly MISSING_PROJECT_CONFIG: "Run 'specforge init' to create configuration";
|
|
139
|
+
readonly MISSING_API_KEY: "Run 'specforge login' to authenticate";
|
|
140
|
+
readonly INVALID_API_KEY_FORMAT: "Get a valid API key from https://specforge.com.br/settings/api-keys";
|
|
141
|
+
readonly EXPIRED_API_KEY: "Run 'specforge login --force' to re-authenticate";
|
|
142
|
+
readonly CONNECTION_FAILED: "Check your internet connection";
|
|
143
|
+
readonly CONNECTION_TIMEOUT: "Check your internet connection or try again later";
|
|
144
|
+
readonly PROJECT_NOT_ACCESSIBLE: "Run 'specforge init' to reconfigure project";
|
|
145
|
+
readonly SPEC_NOT_ACCESSIBLE: "Run 'specforge init' to reconfigure specification";
|
|
146
|
+
readonly NO_PROJECT_CONFIGURED: "Run 'specforge init' to configure a project";
|
|
147
|
+
};
|
|
148
|
+
/**
|
|
149
|
+
* Create a passing check result
|
|
150
|
+
*/
|
|
151
|
+
export declare function createPassResult(name: string, message: string, metadata?: Record<string, unknown>): CheckResult;
|
|
152
|
+
/**
|
|
153
|
+
* Create a failing check result
|
|
154
|
+
*/
|
|
155
|
+
export declare function createFailResult(name: string, message: string, fix?: string, metadata?: Record<string, unknown>): CheckResult;
|
|
156
|
+
/**
|
|
157
|
+
* Create a warning check result
|
|
158
|
+
*/
|
|
159
|
+
export declare function createWarnResult(name: string, message: string, fix?: string, metadata?: Record<string, unknown>): CheckResult;
|
|
160
|
+
/**
|
|
161
|
+
* Calculate summary from check results
|
|
162
|
+
*/
|
|
163
|
+
export declare function calculateSummary(checks: Record<CheckCategory, CheckResult[]>): DoctorSummary;
|
|
164
|
+
/**
|
|
165
|
+
* Create an empty report structure
|
|
166
|
+
*/
|
|
167
|
+
export declare function createEmptyReport(): DoctorReport;
|
|
168
|
+
/**
|
|
169
|
+
* Check if the report has any failures
|
|
170
|
+
*/
|
|
171
|
+
export declare function hasFailures(report: DoctorReport): boolean;
|
|
172
|
+
/**
|
|
173
|
+
* Check if the report has any warnings
|
|
174
|
+
*/
|
|
175
|
+
export declare function hasWarnings(report: DoctorReport): boolean;
|
|
176
|
+
/**
|
|
177
|
+
* Get status icon for display
|
|
178
|
+
*/
|
|
179
|
+
export declare function getStatusIcon(status: CheckStatus): string;
|
|
180
|
+
//# sourceMappingURL=doctor.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.types.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/doctor.types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
const CHECK_CATEGORIES = [
|
|
2
|
+
{
|
|
3
|
+
id: "configuration",
|
|
4
|
+
name: "Configuration",
|
|
5
|
+
description: "Config file presence and validity"
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
id: "authentication",
|
|
9
|
+
name: "Authentication",
|
|
10
|
+
description: "API key format and authentication"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
id: "connection",
|
|
14
|
+
name: "Connection",
|
|
15
|
+
description: "API connectivity and response time"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
id: "projectAccess",
|
|
19
|
+
name: "Project Access",
|
|
20
|
+
description: "Access to configured project and specification"
|
|
21
|
+
}
|
|
22
|
+
];
|
|
23
|
+
const CONFIG_CHECK_NAMES = {
|
|
24
|
+
CHANNEL: "Channel",
|
|
25
|
+
MCP_CONFIG_FOUND: ".mcp.json found",
|
|
26
|
+
PROJECT_CONFIG_FOUND: "project config found",
|
|
27
|
+
GLOBAL_CONFIG_DIR: "Global config",
|
|
28
|
+
API_KEY_CONFIGURED: "API key configured",
|
|
29
|
+
PLANNING_SESSION: "Active planning session"
|
|
30
|
+
};
|
|
31
|
+
const AUTH_CHECK_NAMES = {
|
|
32
|
+
API_KEY_FORMAT: "API key format valid",
|
|
33
|
+
API_KEY_AUTHENTICATED: "API key authenticated",
|
|
34
|
+
USER_INFO: "User info"
|
|
35
|
+
};
|
|
36
|
+
const CONNECTION_CHECK_NAMES = {
|
|
37
|
+
API_ENDPOINT_REACHABLE: "API endpoint reachable",
|
|
38
|
+
RESPONSE_TIME: "Response time"
|
|
39
|
+
};
|
|
40
|
+
const PROJECT_CHECK_NAMES = {
|
|
41
|
+
PROJECT_ACCESSIBLE: "Default project accessible",
|
|
42
|
+
SPECIFICATION_ACCESSIBLE: "Default specification accessible",
|
|
43
|
+
IMPLEMENTATION_SESSION: "Implementation session"
|
|
44
|
+
};
|
|
45
|
+
const PERFORMANCE_THRESHOLDS = {
|
|
46
|
+
/** Response time warning threshold in ms */
|
|
47
|
+
RESPONSE_TIME_WARNING: 500,
|
|
48
|
+
/** Response time error threshold in ms */
|
|
49
|
+
RESPONSE_TIME_ERROR: 5e3,
|
|
50
|
+
/** Connection timeout in ms */
|
|
51
|
+
CONNECTION_TIMEOUT: 1e4
|
|
52
|
+
};
|
|
53
|
+
const API_KEY_VALIDATION = {
|
|
54
|
+
/** Required prefix for live API keys */
|
|
55
|
+
PREFIX: "sf_live_",
|
|
56
|
+
/** Minimum length for valid API key */
|
|
57
|
+
MIN_LENGTH: 28
|
|
58
|
+
};
|
|
59
|
+
const FIX_SUGGESTIONS = {
|
|
60
|
+
MISSING_MCP_CONFIG: "Run 'specforge init' to create configuration",
|
|
61
|
+
MISSING_PROJECT_CONFIG: "Run 'specforge init' to create configuration",
|
|
62
|
+
MISSING_API_KEY: "Run 'specforge login' to authenticate",
|
|
63
|
+
INVALID_API_KEY_FORMAT: "Get a valid API key from https://specforge.com.br/settings/api-keys",
|
|
64
|
+
EXPIRED_API_KEY: "Run 'specforge login --force' to re-authenticate",
|
|
65
|
+
CONNECTION_FAILED: "Check your internet connection",
|
|
66
|
+
CONNECTION_TIMEOUT: "Check your internet connection or try again later",
|
|
67
|
+
PROJECT_NOT_ACCESSIBLE: "Run 'specforge init' to reconfigure project",
|
|
68
|
+
SPEC_NOT_ACCESSIBLE: "Run 'specforge init' to reconfigure specification",
|
|
69
|
+
NO_PROJECT_CONFIGURED: "Run 'specforge init' to configure a project"
|
|
70
|
+
};
|
|
71
|
+
function createPassResult(name, message, metadata) {
|
|
72
|
+
return { name, status: "pass", message, metadata };
|
|
73
|
+
}
|
|
74
|
+
function createFailResult(name, message, fix, metadata) {
|
|
75
|
+
return { name, status: "fail", message, fix, metadata };
|
|
76
|
+
}
|
|
77
|
+
function createWarnResult(name, message, fix, metadata) {
|
|
78
|
+
return { name, status: "warn", message, fix, metadata };
|
|
79
|
+
}
|
|
80
|
+
function calculateSummary(checks) {
|
|
81
|
+
const allChecks = Object.values(checks).flat();
|
|
82
|
+
return {
|
|
83
|
+
passed: allChecks.filter((c) => c.status === "pass").length,
|
|
84
|
+
failed: allChecks.filter((c) => c.status === "fail").length,
|
|
85
|
+
warnings: allChecks.filter((c) => c.status === "warn").length,
|
|
86
|
+
total: allChecks.length
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
function createEmptyReport() {
|
|
90
|
+
return {
|
|
91
|
+
checks: {
|
|
92
|
+
configuration: [],
|
|
93
|
+
authentication: [],
|
|
94
|
+
connection: [],
|
|
95
|
+
projectAccess: []
|
|
96
|
+
},
|
|
97
|
+
summary: {
|
|
98
|
+
passed: 0,
|
|
99
|
+
failed: 0,
|
|
100
|
+
warnings: 0,
|
|
101
|
+
total: 0
|
|
102
|
+
},
|
|
103
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function hasFailures(report) {
|
|
107
|
+
return report.summary.failed > 0;
|
|
108
|
+
}
|
|
109
|
+
function hasWarnings(report) {
|
|
110
|
+
return report.summary.warnings > 0;
|
|
111
|
+
}
|
|
112
|
+
function getStatusIcon(status) {
|
|
113
|
+
switch (status) {
|
|
114
|
+
case "pass":
|
|
115
|
+
return "\u2713";
|
|
116
|
+
case "fail":
|
|
117
|
+
return "\u2717";
|
|
118
|
+
case "warn":
|
|
119
|
+
return "\u26A0";
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
export {
|
|
123
|
+
API_KEY_VALIDATION,
|
|
124
|
+
AUTH_CHECK_NAMES,
|
|
125
|
+
CHECK_CATEGORIES,
|
|
126
|
+
CONFIG_CHECK_NAMES,
|
|
127
|
+
CONNECTION_CHECK_NAMES,
|
|
128
|
+
FIX_SUGGESTIONS,
|
|
129
|
+
PERFORMANCE_THRESHOLDS,
|
|
130
|
+
PROJECT_CHECK_NAMES,
|
|
131
|
+
calculateSummary,
|
|
132
|
+
createEmptyReport,
|
|
133
|
+
createFailResult,
|
|
134
|
+
createPassResult,
|
|
135
|
+
createWarnResult,
|
|
136
|
+
getStatusIcon,
|
|
137
|
+
hasFailures,
|
|
138
|
+
hasWarnings
|
|
139
|
+
};
|
|
140
|
+
//# sourceMappingURL=doctor.types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/cli/commands/doctor.types.ts"],"sourcesContent":["/**\n * Doctor Command Types\n *\n * Type definitions for the doctor command health checks.\n */\n\n/**\n * Doctor command options from Commander\n */\nexport interface DoctorOptions {\n /** Output as JSON instead of formatted text */\n json?: boolean;\n /** Attempt to fix issues automatically */\n fix?: boolean;\n}\n\n/**\n * Check status result\n */\nexport type CheckStatus = 'pass' | 'fail' | 'warn';\n\n/**\n * Individual check result\n */\nexport interface CheckResult {\n /** Name/title of the check */\n name: string;\n /** Status of the check */\n status: CheckStatus;\n /** Detailed message about the result */\n message: string;\n /** Fix suggestion if check failed/warned */\n fix?: string;\n /** Additional metadata for JSON output */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Check category names\n */\nexport type CheckCategory = 'configuration' | 'authentication' | 'connection' | 'projectAccess';\n\n/**\n * Doctor report structure\n */\nexport interface DoctorReport {\n /** Check results grouped by category */\n checks: Record<CheckCategory, CheckResult[]>;\n /** Summary counts */\n summary: DoctorSummary;\n /** Timestamp of the check */\n timestamp: string;\n /** Version of the CLI */\n version?: string;\n}\n\n/**\n * Doctor report summary\n */\nexport interface DoctorSummary {\n /** Number of passed checks */\n passed: number;\n /** Number of failed checks */\n failed: number;\n /** Number of warnings */\n warnings: number;\n /** Total number of checks */\n total: number;\n}\n\n/**\n * Check category display info\n */\nexport interface CheckCategoryInfo {\n /** Category identifier */\n id: CheckCategory;\n /** Display name */\n name: string;\n /** Description */\n description: string;\n}\n\n/**\n * Check category definitions with display info\n */\nexport const CHECK_CATEGORIES: CheckCategoryInfo[] = [\n {\n id: 'configuration',\n name: 'Configuration',\n description: 'Config file presence and validity',\n },\n {\n id: 'authentication',\n name: 'Authentication',\n description: 'API key format and authentication',\n },\n {\n id: 'connection',\n name: 'Connection',\n description: 'API connectivity and response time',\n },\n {\n id: 'projectAccess',\n name: 'Project Access',\n description: 'Access to configured project and specification',\n },\n];\n\n/**\n * Check name constants for configuration checks\n */\nexport const CONFIG_CHECK_NAMES = {\n CHANNEL: 'Channel',\n MCP_CONFIG_FOUND: '.mcp.json found',\n PROJECT_CONFIG_FOUND: 'project config found',\n GLOBAL_CONFIG_DIR: 'Global config',\n API_KEY_CONFIGURED: 'API key configured',\n PLANNING_SESSION: 'Active planning session',\n} as const;\n\n/**\n * Check name constants for authentication checks\n */\nexport const AUTH_CHECK_NAMES = {\n API_KEY_FORMAT: 'API key format valid',\n API_KEY_AUTHENTICATED: 'API key authenticated',\n USER_INFO: 'User info',\n} as const;\n\n/**\n * Check name constants for connection checks\n */\nexport const CONNECTION_CHECK_NAMES = {\n API_ENDPOINT_REACHABLE: 'API endpoint reachable',\n RESPONSE_TIME: 'Response time',\n} as const;\n\n/**\n * Check name constants for project access checks\n */\nexport const PROJECT_CHECK_NAMES = {\n PROJECT_ACCESSIBLE: 'Default project accessible',\n SPECIFICATION_ACCESSIBLE: 'Default specification accessible',\n IMPLEMENTATION_SESSION: 'Implementation session',\n} as const;\n\n/**\n * Thresholds for performance checks\n */\nexport const PERFORMANCE_THRESHOLDS = {\n /** Response time warning threshold in ms */\n RESPONSE_TIME_WARNING: 500,\n /** Response time error threshold in ms */\n RESPONSE_TIME_ERROR: 5000,\n /** Connection timeout in ms */\n CONNECTION_TIMEOUT: 10000,\n} as const;\n\n/**\n * API key validation constants\n */\nexport const API_KEY_VALIDATION = {\n /** Required prefix for live API keys */\n PREFIX: 'sf_live_',\n /** Minimum length for valid API key */\n MIN_LENGTH: 28,\n} as const;\n\n/**\n * Fix suggestion templates\n */\nexport const FIX_SUGGESTIONS = {\n MISSING_MCP_CONFIG: \"Run 'specforge init' to create configuration\",\n MISSING_PROJECT_CONFIG: \"Run 'specforge init' to create configuration\",\n MISSING_API_KEY: \"Run 'specforge login' to authenticate\",\n INVALID_API_KEY_FORMAT: 'Get a valid API key from https://specforge.com.br/settings/api-keys',\n EXPIRED_API_KEY: \"Run 'specforge login --force' to re-authenticate\",\n CONNECTION_FAILED: 'Check your internet connection',\n CONNECTION_TIMEOUT: 'Check your internet connection or try again later',\n PROJECT_NOT_ACCESSIBLE: \"Run 'specforge init' to reconfigure project\",\n SPEC_NOT_ACCESSIBLE: \"Run 'specforge init' to reconfigure specification\",\n NO_PROJECT_CONFIGURED: \"Run 'specforge init' to configure a project\",\n} as const;\n\n/**\n * Create a passing check result\n */\nexport function createPassResult(name: string, message: string, metadata?: Record<string, unknown>): CheckResult {\n return { name, status: 'pass', message, metadata };\n}\n\n/**\n * Create a failing check result\n */\nexport function createFailResult(name: string, message: string, fix?: string, metadata?: Record<string, unknown>): CheckResult {\n return { name, status: 'fail', message, fix, metadata };\n}\n\n/**\n * Create a warning check result\n */\nexport function createWarnResult(name: string, message: string, fix?: string, metadata?: Record<string, unknown>): CheckResult {\n return { name, status: 'warn', message, fix, metadata };\n}\n\n/**\n * Calculate summary from check results\n */\nexport function calculateSummary(checks: Record<CheckCategory, CheckResult[]>): DoctorSummary {\n const allChecks = Object.values(checks).flat();\n return {\n passed: allChecks.filter(c => c.status === 'pass').length,\n failed: allChecks.filter(c => c.status === 'fail').length,\n warnings: allChecks.filter(c => c.status === 'warn').length,\n total: allChecks.length,\n };\n}\n\n/**\n * Create an empty report structure\n */\nexport function createEmptyReport(): DoctorReport {\n return {\n checks: {\n configuration: [],\n authentication: [],\n connection: [],\n projectAccess: [],\n },\n summary: {\n passed: 0,\n failed: 0,\n warnings: 0,\n total: 0,\n },\n timestamp: new Date().toISOString(),\n };\n}\n\n/**\n * Check if the report has any failures\n */\nexport function hasFailures(report: DoctorReport): boolean {\n return report.summary.failed > 0;\n}\n\n/**\n * Check if the report has any warnings\n */\nexport function hasWarnings(report: DoctorReport): boolean {\n return report.summary.warnings > 0;\n}\n\n/**\n * Get status icon for display\n */\nexport function getStatusIcon(status: CheckStatus): string {\n switch (status) {\n case 'pass':\n return '✓';\n case 'fail':\n return '✗';\n case 'warn':\n return '⚠';\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feedback Command
|
|
3
|
+
*
|
|
4
|
+
* Lists and submits feedback via the MCP API.
|
|
5
|
+
*/
|
|
6
|
+
import { Command } from 'commander';
|
|
7
|
+
import { FeedbackOptions } from './feedback.types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Feedback list action handler
|
|
10
|
+
*/
|
|
11
|
+
export declare function feedbackAction(options: FeedbackOptions): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Feedback submit action handler
|
|
14
|
+
*/
|
|
15
|
+
export declare function feedbackSubmitAction(options: {
|
|
16
|
+
category: string;
|
|
17
|
+
summary: string;
|
|
18
|
+
severity?: string;
|
|
19
|
+
tool?: string;
|
|
20
|
+
details?: string;
|
|
21
|
+
json?: boolean;
|
|
22
|
+
}): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Register feedback command with Commander
|
|
25
|
+
*/
|
|
26
|
+
export declare function registerFeedbackCommand(program: Command): void;
|
|
27
|
+
//# sourceMappingURL=feedback.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feedback.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/feedback.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,OAAO,EACL,eAAe,EAUhB,MAAM,qBAAqB,CAAC;AAoJ7B;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAgE5E;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAAE;IAClD,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuDhB;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA6D9D"}
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import ora from "ora";
|
|
2
|
+
import { resolveConfig } from "../config/index.js";
|
|
3
|
+
import { ApiClient } from "../../client/api-client.js";
|
|
4
|
+
import { withErrorHandler, CliError } from "../middleware/error-handler.js";
|
|
5
|
+
import { printBlank, printHeader } from "../ui/output.js";
|
|
6
|
+
import { colors } from "../ui/colors.js";
|
|
7
|
+
import {
|
|
8
|
+
VALID_CATEGORIES,
|
|
9
|
+
CATEGORY_COLORS,
|
|
10
|
+
SEVERITY_COLORS,
|
|
11
|
+
isValidCategory,
|
|
12
|
+
truncateSummary
|
|
13
|
+
} from "./feedback.types.js";
|
|
14
|
+
function getCategoryColorFn(category) {
|
|
15
|
+
const colorName = CATEGORY_COLORS[category];
|
|
16
|
+
switch (colorName) {
|
|
17
|
+
case "red":
|
|
18
|
+
return colors.error;
|
|
19
|
+
case "blue":
|
|
20
|
+
return colors.primary;
|
|
21
|
+
case "yellow":
|
|
22
|
+
return colors.warning;
|
|
23
|
+
case "cyan":
|
|
24
|
+
return (s) => colors.primary(s);
|
|
25
|
+
case "magenta":
|
|
26
|
+
return (s) => colors.primary(s);
|
|
27
|
+
default:
|
|
28
|
+
return (s) => s;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function getSeverityColorFn(severity) {
|
|
32
|
+
const colorName = SEVERITY_COLORS[severity];
|
|
33
|
+
switch (colorName) {
|
|
34
|
+
case "red":
|
|
35
|
+
return colors.error;
|
|
36
|
+
case "yellow":
|
|
37
|
+
return colors.warning;
|
|
38
|
+
case "blue":
|
|
39
|
+
return colors.primary;
|
|
40
|
+
case "dim":
|
|
41
|
+
return colors.muted;
|
|
42
|
+
default:
|
|
43
|
+
return (s) => s;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function displayFeedbackTable(entries, total) {
|
|
47
|
+
printBlank();
|
|
48
|
+
printHeader("Feedback");
|
|
49
|
+
printBlank();
|
|
50
|
+
if (entries.length === 0) {
|
|
51
|
+
console.log(colors.muted("No feedback entries found."));
|
|
52
|
+
printBlank();
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const header = [
|
|
56
|
+
"ID".padEnd(24),
|
|
57
|
+
"CATEGORY".padEnd(16),
|
|
58
|
+
"SEVERITY".padEnd(10),
|
|
59
|
+
"TOOL".padEnd(12),
|
|
60
|
+
"SUMMARY"
|
|
61
|
+
].join(" ");
|
|
62
|
+
console.log(colors.muted(header));
|
|
63
|
+
console.log(colors.muted("\u2500".repeat(header.length)));
|
|
64
|
+
for (const entry of entries) {
|
|
65
|
+
const categoryColor = getCategoryColorFn(entry.category);
|
|
66
|
+
const severityColor = getSeverityColorFn(entry.severity);
|
|
67
|
+
const row = [
|
|
68
|
+
entry.id.padEnd(24),
|
|
69
|
+
categoryColor(entry.category.padEnd(16)),
|
|
70
|
+
severityColor(entry.severity.padEnd(10)),
|
|
71
|
+
(entry.tool || "-").padEnd(12),
|
|
72
|
+
truncateSummary(entry.summary)
|
|
73
|
+
].join(" ");
|
|
74
|
+
console.log(row);
|
|
75
|
+
}
|
|
76
|
+
printBlank();
|
|
77
|
+
console.log(colors.muted(`Total: ${total} ${total === 1 ? "entry" : "entries"}`));
|
|
78
|
+
printBlank();
|
|
79
|
+
}
|
|
80
|
+
function displayEmptyState() {
|
|
81
|
+
printBlank();
|
|
82
|
+
console.log(colors.muted("No feedback entries found."));
|
|
83
|
+
console.log(
|
|
84
|
+
colors.muted('Use "specforge feedback submit" to submit feedback.')
|
|
85
|
+
);
|
|
86
|
+
printBlank();
|
|
87
|
+
}
|
|
88
|
+
function formatFeedbackAsToon(entries, total) {
|
|
89
|
+
const lines = ["@feedback"];
|
|
90
|
+
lines.push(` total: ${total}`);
|
|
91
|
+
lines.push(" entries:");
|
|
92
|
+
for (const entry of entries) {
|
|
93
|
+
lines.push(` - ${entry.id}`);
|
|
94
|
+
lines.push(` category: ${entry.category}`);
|
|
95
|
+
lines.push(` severity: ${entry.severity}`);
|
|
96
|
+
if (entry.tool) {
|
|
97
|
+
lines.push(` tool: ${entry.tool}`);
|
|
98
|
+
}
|
|
99
|
+
lines.push(` summary: ${entry.summary}`);
|
|
100
|
+
lines.push(` createdAt: ${entry.createdAt}`);
|
|
101
|
+
}
|
|
102
|
+
return lines.join("\n");
|
|
103
|
+
}
|
|
104
|
+
function createClient() {
|
|
105
|
+
const config = resolveConfig();
|
|
106
|
+
if (!config.apiKey) {
|
|
107
|
+
throw new CliError(
|
|
108
|
+
"Not authenticated",
|
|
109
|
+
1,
|
|
110
|
+
"Run `specforge login` to authenticate first"
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
return new ApiClient(
|
|
114
|
+
{
|
|
115
|
+
apiKey: config.apiKey,
|
|
116
|
+
apiUrl: config.apiUrl,
|
|
117
|
+
debug: config.debug
|
|
118
|
+
},
|
|
119
|
+
{ origin: "cli" }
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
async function feedbackAction(options) {
|
|
123
|
+
const spinner = ora({
|
|
124
|
+
text: "Loading feedback...",
|
|
125
|
+
color: "cyan"
|
|
126
|
+
}).start();
|
|
127
|
+
try {
|
|
128
|
+
if (options.category && !isValidCategory(options.category)) {
|
|
129
|
+
spinner.stop();
|
|
130
|
+
throw new CliError(
|
|
131
|
+
`Invalid category: ${options.category}`,
|
|
132
|
+
1,
|
|
133
|
+
`Valid categories: ${VALID_CATEGORIES.join(", ")}`
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
const limit = options.limit ? parseInt(options.limit, 10) : 10;
|
|
137
|
+
if (isNaN(limit) || limit < 1) {
|
|
138
|
+
spinner.stop();
|
|
139
|
+
throw new CliError("Invalid limit", 1, "Limit must be a positive number");
|
|
140
|
+
}
|
|
141
|
+
const client = createClient();
|
|
142
|
+
const response = await client.call("feedback", {
|
|
143
|
+
operation: "list",
|
|
144
|
+
limit,
|
|
145
|
+
categoryFilter: options.category || void 0
|
|
146
|
+
});
|
|
147
|
+
spinner.stop();
|
|
148
|
+
const entries = response.entries || [];
|
|
149
|
+
const total = response.total || entries.length;
|
|
150
|
+
if (options.json) {
|
|
151
|
+
console.log(JSON.stringify(response, null, 2));
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
if (options.toon) {
|
|
155
|
+
console.log(formatFeedbackAsToon(entries, total));
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
if (entries.length === 0) {
|
|
159
|
+
displayEmptyState();
|
|
160
|
+
} else {
|
|
161
|
+
displayFeedbackTable(entries, total);
|
|
162
|
+
}
|
|
163
|
+
} catch (error) {
|
|
164
|
+
spinner.stop();
|
|
165
|
+
if (error instanceof CliError) {
|
|
166
|
+
throw error;
|
|
167
|
+
}
|
|
168
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
169
|
+
throw new CliError(`Failed to load feedback: ${message}`, 1);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
async function feedbackSubmitAction(options) {
|
|
173
|
+
if (!isValidCategory(options.category)) {
|
|
174
|
+
throw new CliError(
|
|
175
|
+
`Invalid category: ${options.category}`,
|
|
176
|
+
1,
|
|
177
|
+
`Valid categories: ${VALID_CATEGORIES.join(", ")}`
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
const spinner = ora({
|
|
181
|
+
text: "Submitting feedback...",
|
|
182
|
+
color: "cyan"
|
|
183
|
+
}).start();
|
|
184
|
+
try {
|
|
185
|
+
const client = createClient();
|
|
186
|
+
const response = await client.call("feedback", {
|
|
187
|
+
operation: "submit",
|
|
188
|
+
category: options.category,
|
|
189
|
+
summary: options.summary,
|
|
190
|
+
severity: options.severity || "medium",
|
|
191
|
+
tool: options.tool || void 0,
|
|
192
|
+
details: options.details || void 0
|
|
193
|
+
});
|
|
194
|
+
spinner.stop();
|
|
195
|
+
if (options.json) {
|
|
196
|
+
console.log(JSON.stringify(response, null, 2));
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
printBlank();
|
|
200
|
+
console.log(colors.success("\u2713") + " Feedback submitted");
|
|
201
|
+
console.log(colors.muted("\u2500".repeat(40)));
|
|
202
|
+
console.log(colors.muted(` ID: ${response.feedbackId}`));
|
|
203
|
+
console.log(colors.muted(` Category: ${options.category}`));
|
|
204
|
+
console.log(colors.muted(` Summary: ${options.summary}`));
|
|
205
|
+
printBlank();
|
|
206
|
+
} catch (error) {
|
|
207
|
+
spinner.stop();
|
|
208
|
+
if (error instanceof CliError) {
|
|
209
|
+
throw error;
|
|
210
|
+
}
|
|
211
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
212
|
+
throw new CliError(`Failed to submit feedback: ${message}`, 1);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
function registerFeedbackCommand(program) {
|
|
216
|
+
const feedback = program.command("feedback").description("List and submit feedback");
|
|
217
|
+
feedback.option("--json", "Output as JSON").option("--toon", "Output as TOON format").option(
|
|
218
|
+
"--category <category>",
|
|
219
|
+
`Filter by category (${VALID_CATEGORIES.join(", ")})`
|
|
220
|
+
).option("--limit <n>", "Limit number of results", "10").action(withErrorHandler(feedbackAction));
|
|
221
|
+
feedback.command("submit <summary>").description("Submit new feedback").requiredOption(
|
|
222
|
+
"-c, --category <category>",
|
|
223
|
+
`Category (${VALID_CATEGORIES.join(", ")})`
|
|
224
|
+
).option(
|
|
225
|
+
"-s, --severity <severity>",
|
|
226
|
+
"Severity (critical, high, medium, low)",
|
|
227
|
+
"medium"
|
|
228
|
+
).option("-t, --tool <tool>", "Related MCP tool").option("-d, --details <details>", "Extended description").option("--json", "Output as JSON").action(withErrorHandler(async (summary, opts) => {
|
|
229
|
+
await feedbackSubmitAction({
|
|
230
|
+
summary,
|
|
231
|
+
category: opts.category,
|
|
232
|
+
severity: opts.severity,
|
|
233
|
+
tool: opts.tool,
|
|
234
|
+
details: opts.details,
|
|
235
|
+
json: !!opts.json
|
|
236
|
+
});
|
|
237
|
+
}));
|
|
238
|
+
feedback.addHelpText(
|
|
239
|
+
"after",
|
|
240
|
+
`
|
|
241
|
+
Examples:
|
|
242
|
+
$ specforge feedback # List all feedback
|
|
243
|
+
$ specforge feedback --json # Output as JSON
|
|
244
|
+
$ specforge feedback --category bug # Filter by category
|
|
245
|
+
$ specforge feedback submit "Tool X fails" # Submit feedback
|
|
246
|
+
-c bug -s high -t action_work_session
|
|
247
|
+
|
|
248
|
+
Categories:
|
|
249
|
+
${colors.error("bug")} - Something isn't working correctly
|
|
250
|
+
${colors.primary("feature_request")} - New capability suggestion
|
|
251
|
+
${colors.warning("usability")} - UX/DX improvement
|
|
252
|
+
${colors.primary("documentation")} - Docs unclear or missing
|
|
253
|
+
${colors.primary("performance")} - Speed/efficiency issue
|
|
254
|
+
`
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
export {
|
|
258
|
+
feedbackAction,
|
|
259
|
+
feedbackSubmitAction,
|
|
260
|
+
registerFeedbackCommand
|
|
261
|
+
};
|
|
262
|
+
//# sourceMappingURL=feedback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/cli/commands/feedback.ts"],"sourcesContent":["/**\n * Feedback Command\n *\n * Lists and submits feedback via the MCP API.\n */\n\nimport { Command } from 'commander';\nimport ora from 'ora';\nimport { resolveConfig } from '../config/index.js';\nimport { ApiClient } from '../../client/api-client.js';\nimport { withErrorHandler, CliError } from '../middleware/error-handler.js';\nimport { printBlank, printHeader } from '../ui/output.js';\nimport { colors } from '../ui/colors.js';\nimport {\n FeedbackOptions,\n FeedbackListEntry,\n FeedbackListResponse,\n VALID_CATEGORIES,\n CATEGORY_COLORS,\n SEVERITY_COLORS,\n isValidCategory,\n truncateSummary,\n type FeedbackCategory,\n type FeedbackSeverity,\n} from './feedback.types.js';\n\n/**\n * Get chalk color function for category\n */\nfunction getCategoryColorFn(category: FeedbackCategory): (s: string) => string {\n const colorName = CATEGORY_COLORS[category];\n switch (colorName) {\n case 'red':\n return colors.error;\n case 'blue':\n return colors.primary;\n case 'yellow':\n return colors.warning;\n case 'cyan':\n return (s: string) => colors.primary(s);\n case 'magenta':\n return (s: string) => colors.primary(s);\n default:\n return (s: string) => s;\n }\n}\n\n/**\n * Get chalk color function for severity\n */\nfunction getSeverityColorFn(severity: FeedbackSeverity): (s: string) => string {\n const colorName = SEVERITY_COLORS[severity];\n switch (colorName) {\n case 'red':\n return colors.error;\n case 'yellow':\n return colors.warning;\n case 'blue':\n return colors.primary;\n case 'dim':\n return colors.muted;\n default:\n return (s: string) => s;\n }\n}\n\n/**\n * Display feedback entries in table format\n */\nfunction displayFeedbackTable(entries: FeedbackListEntry[], total: number): void {\n printBlank();\n printHeader('Feedback');\n printBlank();\n\n if (entries.length === 0) {\n console.log(colors.muted('No feedback entries found.'));\n printBlank();\n return;\n }\n\n // Table header\n const header = [\n 'ID'.padEnd(24),\n 'CATEGORY'.padEnd(16),\n 'SEVERITY'.padEnd(10),\n 'TOOL'.padEnd(12),\n 'SUMMARY',\n ].join(' ');\n console.log(colors.muted(header));\n console.log(colors.muted('─'.repeat(header.length)));\n\n // Table rows\n for (const entry of entries) {\n const categoryColor = getCategoryColorFn(entry.category);\n const severityColor = getSeverityColorFn(entry.severity);\n\n const row = [\n entry.id.padEnd(24),\n categoryColor(entry.category.padEnd(16)),\n severityColor(entry.severity.padEnd(10)),\n (entry.tool || '-').padEnd(12),\n truncateSummary(entry.summary),\n ].join(' ');\n\n console.log(row);\n }\n\n printBlank();\n console.log(colors.muted(`Total: ${total} ${total === 1 ? 'entry' : 'entries'}`));\n printBlank();\n}\n\n/**\n * Display empty state\n */\nfunction displayEmptyState(): void {\n printBlank();\n console.log(colors.muted('No feedback entries found.'));\n console.log(\n colors.muted('Use \"specforge feedback submit\" to submit feedback.')\n );\n printBlank();\n}\n\n/**\n * Format feedback as TOON\n */\nfunction formatFeedbackAsToon(entries: FeedbackListEntry[], total: number): string {\n const lines: string[] = ['@feedback'];\n lines.push(` total: ${total}`);\n lines.push(' entries:');\n\n for (const entry of entries) {\n lines.push(` - ${entry.id}`);\n lines.push(` category: ${entry.category}`);\n lines.push(` severity: ${entry.severity}`);\n if (entry.tool) {\n lines.push(` tool: ${entry.tool}`);\n }\n lines.push(` summary: ${entry.summary}`);\n lines.push(` createdAt: ${entry.createdAt}`);\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Create an ApiClient from resolved config\n */\nfunction createClient(): ApiClient {\n const config = resolveConfig();\n\n if (!config.apiKey) {\n throw new CliError(\n 'Not authenticated',\n 1,\n 'Run `specforge login` to authenticate first'\n );\n }\n\n // M9.7: the human CLI surface stamps origin via the `X-SpecForge-Origin: cli`\n // header (the backend dropped the request-body `source` field in M7.4).\n return new ApiClient(\n {\n apiKey: config.apiKey,\n apiUrl: config.apiUrl,\n debug: config.debug,\n },\n { origin: 'cli' },\n );\n}\n\n/**\n * Feedback list action handler\n */\nexport async function feedbackAction(options: FeedbackOptions): Promise<void> {\n const spinner = ora({\n text: 'Loading feedback...',\n color: 'cyan',\n }).start();\n\n try {\n // Validate category filter if provided\n if (options.category && !isValidCategory(options.category)) {\n spinner.stop();\n throw new CliError(\n `Invalid category: ${options.category}`,\n 1,\n `Valid categories: ${VALID_CATEGORIES.join(', ')}`\n );\n }\n\n // Parse limit\n const limit = options.limit ? parseInt(options.limit, 10) : 10;\n if (isNaN(limit) || limit < 1) {\n spinner.stop();\n throw new CliError('Invalid limit', 1, 'Limit must be a positive number');\n }\n\n const client = createClient();\n\n const response = await client.call<FeedbackListResponse>('feedback', {\n operation: 'list',\n limit,\n categoryFilter: options.category || undefined,\n });\n\n spinner.stop();\n\n const entries: FeedbackListEntry[] = response.entries || [];\n const total = response.total || entries.length;\n\n // Output based on format\n if (options.json) {\n console.log(JSON.stringify(response, null, 2));\n return;\n }\n\n if (options.toon) {\n console.log(formatFeedbackAsToon(entries, total));\n return;\n }\n\n // Default: table display\n if (entries.length === 0) {\n displayEmptyState();\n } else {\n displayFeedbackTable(entries, total);\n }\n } catch (error) {\n spinner.stop();\n\n if (error instanceof CliError) {\n throw error;\n }\n\n const message = error instanceof Error ? error.message : 'Unknown error';\n throw new CliError(`Failed to load feedback: ${message}`, 1);\n }\n}\n\n/**\n * Feedback submit action handler\n */\nexport async function feedbackSubmitAction(options: {\n category: string;\n summary: string;\n severity?: string;\n tool?: string;\n details?: string;\n json?: boolean;\n}): Promise<void> {\n // Validate category\n if (!isValidCategory(options.category)) {\n throw new CliError(\n `Invalid category: ${options.category}`,\n 1,\n `Valid categories: ${VALID_CATEGORIES.join(', ')}`\n );\n }\n\n const spinner = ora({\n text: 'Submitting feedback...',\n color: 'cyan',\n }).start();\n\n try {\n const client = createClient();\n\n const response = await client.call<{\n success: boolean;\n feedbackId: string;\n message: string;\n }>('feedback', {\n operation: 'submit',\n category: options.category,\n summary: options.summary,\n severity: options.severity || 'medium',\n tool: options.tool || undefined,\n details: options.details || undefined,\n });\n\n spinner.stop();\n\n if (options.json) {\n console.log(JSON.stringify(response, null, 2));\n return;\n }\n\n printBlank();\n console.log(colors.success('✓') + ' Feedback submitted');\n console.log(colors.muted('─'.repeat(40)));\n console.log(colors.muted(` ID: ${response.feedbackId}`));\n console.log(colors.muted(` Category: ${options.category}`));\n console.log(colors.muted(` Summary: ${options.summary}`));\n printBlank();\n } catch (error) {\n spinner.stop();\n\n if (error instanceof CliError) {\n throw error;\n }\n\n const message = error instanceof Error ? error.message : 'Unknown error';\n throw new CliError(`Failed to submit feedback: ${message}`, 1);\n }\n}\n\n/**\n * Register feedback command with Commander\n */\nexport function registerFeedbackCommand(program: Command): void {\n const feedback = program\n .command('feedback')\n .description('List and submit feedback');\n\n // Default: list feedback\n feedback\n .option('--json', 'Output as JSON')\n .option('--toon', 'Output as TOON format')\n .option(\n '--category <category>',\n `Filter by category (${VALID_CATEGORIES.join(', ')})`\n )\n .option('--limit <n>', 'Limit number of results', '10')\n .action(withErrorHandler(feedbackAction));\n\n // Submit subcommand\n feedback\n .command('submit <summary>')\n .description('Submit new feedback')\n .requiredOption(\n '-c, --category <category>',\n `Category (${VALID_CATEGORIES.join(', ')})`\n )\n .option(\n '-s, --severity <severity>',\n 'Severity (critical, high, medium, low)',\n 'medium'\n )\n .option('-t, --tool <tool>', 'Related MCP tool')\n .option('-d, --details <details>', 'Extended description')\n .option('--json', 'Output as JSON')\n .action(withErrorHandler(async (summary: string, opts: Record<string, string | undefined>) => {\n await feedbackSubmitAction({\n summary,\n category: opts.category!,\n severity: opts.severity,\n tool: opts.tool,\n details: opts.details,\n json: !!opts.json,\n });\n }));\n\n feedback.addHelpText(\n 'after',\n `\nExamples:\n $ specforge feedback # List all feedback\n $ specforge feedback --json # Output as JSON\n $ specforge feedback --category bug # Filter by category\n $ specforge feedback submit \"Tool X fails\" # Submit feedback\n -c bug -s high -t action_work_session\n\nCategories:\n ${colors.error('bug')} - Something isn't working correctly\n ${colors.primary('feature_request')} - New capability suggestion\n ${colors.warning('usability')} - UX/DX improvement\n ${colors.primary('documentation')} - Docs unclear or missing\n ${colors.primary('performance')} - Speed/efficiency issue\n`\n );\n}\n"],"mappings":"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","names":[]}
|